diff --git a/.gitignore b/.gitignore index 0189708..c967ead 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,4 @@ Carthage # # Note: if you ignore the Pods directory, make sure to uncomment # `pod install` in .travis.yml -# +Example/Pods diff --git a/.travis.yml b/.travis.yml index e4ce1ee..2662ad4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,7 @@ language: objective-c # podfile: Example/Podfile before_install: - gem install cocoapods # Since Travis is not always on latest version -- pod repo update -#- pod install --project-directory=Example --repo-update +- pod install --project-directory=Example --repo-update script: - set -o pipefail && xcodebuild test -workspace Example/ACKReactiveExtensions.xcworkspace -scheme ACKReactiveExtensions-Example -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.1' ONLY_ACTIVE_ARCH=NO | xcpretty - travis_wait 120 pod lib lint --allow-warnings diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock deleted file mode 100644 index 3950d0b..0000000 --- a/Example/Pods/Manifest.lock +++ /dev/null @@ -1,90 +0,0 @@ -PODS: - - ACKReactiveExtensions (2.3.0): - - ACKReactiveExtensions/Core (= 2.3.0) - - ACKReactiveExtensions/UIKit (= 2.3.0) - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/Argo (2.3.0): - - Argo (< 5.0, >= 4.1.2) - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/Core (2.3.0): - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/Marshal (2.3.0): - - ACKReactiveExtensions/Core - - Marshal (~> 1.2) - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/Reachability (2.3.0): - - ACKReactiveExtensions/Core - - Reachability - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/Realm (2.3.0): - - ACKReactiveExtensions/Core - - ReactiveCocoa (~> 5.0) - - RealmSwift (~> 2.1) - - ACKReactiveExtensions/SDWebImage (2.3.0): - - ACKReactiveExtensions/Core - - ReactiveCocoa (~> 5.0) - - SDWebImage (~> 4.0) - - ACKReactiveExtensions/UIKit (2.3.0): - - ACKReactiveExtensions/Core - - ReactiveCocoa (~> 5.0) - - ACKReactiveExtensions/WebKit (2.3.0): - - ACKReactiveExtensions/Core - - ReactiveCocoa (~> 5.0) - - Argo (4.1.2): - - Runes (>= 4.0.0) - - Curry (3.0.0) - - Marshal (1.2.4) - - Nimble (5.1.1) - - Quick (0.10.0) - - Reachability (3.2) - - ReactiveCocoa (5.0.1): - - ReactiveSwift (~> 1.1) - - ReactiveSwift (1.1.0): - - Result (~> 3.1) - - Realm (2.1.2): - - Realm/Headers (= 2.1.2) - - Realm/Headers (2.1.2) - - RealmSwift (2.1.2): - - Realm (= 2.1.2) - - Result (3.1.0) - - Runes (4.0.1) - - SDWebImage (4.0.0): - - SDWebImage/Core (= 4.0.0) - - SDWebImage/Core (4.0.0) - -DEPENDENCIES: - - ACKReactiveExtensions (from `../`) - - ACKReactiveExtensions/Argo (from `../`) - - ACKReactiveExtensions/Marshal (from `../`) - - ACKReactiveExtensions/Reachability (from `../`) - - ACKReactiveExtensions/Realm (from `../`) - - ACKReactiveExtensions/SDWebImage (from `../`) - - ACKReactiveExtensions/WebKit (from `../`) - - Curry (~> 3.0) - - Nimble (~> 5.0) - - Quick (~> 0.10) - - Result (~> 3.1) - -EXTERNAL SOURCES: - ACKReactiveExtensions: - :path: "../" - -SPEC CHECKSUMS: - ACKReactiveExtensions: f35f2afcd9e5b324d92883c94b4c3d724118781f - Argo: 5db06502fc1222d83011f574243089dab25202ff - Curry: eb3d2c75aec678b3cc7fb2729d2ad6dd121531d1 - Marshal: 8e04e6624e506921db7143b0bfd83caee03f32d6 - Nimble: 415e3aa3267e7bc2c96b05fa814ddea7bb686a29 - Quick: 5d290df1c69d5ee2f0729956dcf0fd9a30447eaa - Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 - ReactiveCocoa: f577006aa6c7b0b08020109ebaae3b77ada00adc - ReactiveSwift: 2f4e4a02e5a5c87ea63f5fe667163ce2a67cbb57 - Realm: efe855f4d977c8ce5a82d3116d9f1ff155a6550c - RealmSwift: 17d6ee30b6f9df86364408c2197492e33bfea567 - Result: 4e3ed5995ed94d0cd6a09be9a431fce3f3624bbf - Runes: ff20f163b478ac2c0e18158d6086fd5b1997f983 - SDWebImage: 76a6348bdc74eb5a55dd08a091ef298e56b55e41 - -PODFILE CHECKSUM: 1d0475767d76bb45cefcaceddd19be37d22fedc7 - -COCOAPODS: 1.2.0 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index d411472..0000000 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,5087 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 019ECB09A9E31D2A4256499031A0C930 /* Runes.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE589D63713D983B7A2CC10D113B938D /* Runes.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 02591775914FEC8F71F091689667029A /* Curry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B1B4AF823C9F4BA40CFD18D903C114 /* Curry.swift */; }; - 026C120AAA7AA799CBE340B33D83D0A3 /* SDWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BBB569FFF4629F64B98D1DE16E37BE9 /* SDWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0452F06F534451551D51070D6FF46B19 /* RLMSyncManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CFCCDC4D7CE01D0325D2BFC246BDD146 /* RLMSyncManager.h */; }; - 04766050A11C6E86D5C2762A7283DB1F /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33EA03A6970E732035AFB8C2C7200168 /* Result.swift */; }; - 047A68C646E00EB6D7D4D7343B801D09 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5956ED9D5D7E478706DC7E2A5E06C24B /* AdapterProtocols.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 04BB0E73573A81B23B3393B0912DD037 /* RealmExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F98732B1434617349CC7A856209E7BD5 /* RealmExtensions.swift */; }; - 0511654D6963427A5830D45DACFE6064 /* ObjCRuntimeAliases.m in Sources */ = {isa = PBXBuildFile; fileRef = FE34C1D3F9802D08338B451C4791163E /* ObjCRuntimeAliases.m */; }; - 0587E9945FE0EA064A7552DB9D34A98E /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = AE00E475E56003AD4B4A2AEE0DE038EA /* QuickSpec.m */; }; - 07158F4EAEED03D1C096A264FFF7F4D3 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B0E4E4C02341EF78603E824B2733137 /* Optional.swift */; }; - 07722FBCF6B380961B9D2832D5883F45 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = A21F857CC9433B920B0AB4D045D27935 /* BeGreaterThan.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 07D7DE59C1369D3790FACB0847738FA5 /* RLMAuthResponseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BAFEAED1D1237AB634CF4E6CFF8CAE7 /* RLMAuthResponseModel.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 08924C40CB922735E6F138F404DB8FB7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 09402F4421E1C056D442CB795B8720F7 /* Realm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C83184A660ADDBE83E50CB93257B58CD /* Realm.h */; }; - 0ADD5E09DA2E1537FA19E10893C86D4E /* sync_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F779D8E6F5B54B674B2C1DE7147A2081 /* sync_manager.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 0AEC20AACF9B10846830274E3B2AA6FD /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1496F2101AA68CBAF4B9E8ECBA7FBC6 /* BeLogical.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 0B15A1CAD338D37362D14D12EAF89CB4 /* NSObject+ReactiveExtensionsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC256ADDA6D2D62C6DD213773A7D60BE /* NSObject+ReactiveExtensionsProvider.swift */; }; - 0B708B9ABAC97D45FB17A994F35BADE6 /* NSImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7DA7E139F874EC8DF9C7A6D1E80337 /* NSImage+WebCache.m */; }; - 0B999D2E8FA80F48D33C387CD2E9977F /* Curry-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CB9A2CC4443A5D98CC7C8883879D405 /* Curry-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0BBECF3451BA6FE8CB28BAFCE21F3429 /* RLMMigration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B9C086F9429415130B95A4D9BD539C4A /* RLMMigration_Private.h */; }; - 0BCEEC65C8DB4F60A0EFD9EB193BB99A /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58B017B22770D3C49FB229911CCA63F /* Configuration.swift */; }; - 0C309D486F03BE8D49BDB723BBB583FA /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03C9AF42C06446ECC6AAFF6D6802866D /* thread_confined.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 0CA86759153D45C3EBF8C648919EB6D0 /* RLMCollection.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 09EBF73F678AC49042C057CECA6D9C9B /* RLMCollection.h */; }; - 0CF70D2D57B6C4E2F188497BB68302B3 /* RLMRealmConfiguration+Sync.mm in Sources */ = {isa = PBXBuildFile; fileRef = AF4D7C33BF3FCD7F5980750DFE079618 /* RLMRealmConfiguration+Sync.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 0D0A84C74D45C19FECD0B6185DC37F6D /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F87A26DBCDFFF48E7D97BF667F86B1 /* Dictionary.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 0D3E0358F622711CD56F3694492773A2 /* RLMSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 33FD8512741E03356DC3075014CB736C /* RLMSchema_Private.h */; }; - 0E294C5A0EFD02EC307BD1D6EE73115B /* ObjC+Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB12851B9DEC440905468EFB3DF8 /* ObjC+Messages.swift */; }; - 0ECEEBC712D404AA6CF1E76A9284BFF9 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = CCD6D21B1824B199A28FD405F7F080B9 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0F0BB306CA857876353E208376BCD352 /* catDecoded.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B548C79D533C48D007E1AC4D8658EC9 /* catDecoded.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 0F62ED582583864D79760F5FA3536E3E /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6AFC9457459627BE4924716346183F /* Signal.swift */; }; - 10C007DB3ED975F6995738B17E02A0CC /* RLMRealmConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C09657AF9A1B91C4D3AEDB678B9BEAD0 /* RLMRealmConfiguration_Private.h */; }; - 110A640A9BE45841BA938B4C29EF5446 /* ThrowAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A483371BD64280D772DF8835B57A97 /* ThrowAssertion.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 11D48C81BE09541E54A4174D45E2B5B1 /* RLMSyncConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = EEDE876B3316432FB3B299AFCF04D14A /* RLMSyncConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 11DDB2DB3F2C88EFC12DB242CDF47568 /* RLMOptionalBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 60A002572AC20E5406A90AAC57DFF042 /* RLMOptionalBase.h */; }; - 11DDF57ABADC4FAB95DA443AFC12AF47 /* RLMProperty_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AC6B8BF65E2C5C0DB2344F42211B2AE /* RLMProperty_Private.h */; }; - 11F5A28A612C7CE8E57C31F0AEA9FCAF /* RLMArrayLinkView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0894A8ECFDE6892A88F6E589924D3B30 /* RLMArrayLinkView.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 125DDC49328BC08C93205BD98DB0CFF7 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F59BF4AD6298FBBDEF7F8FFC6E2DFC /* Optional.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 127CD37052B8E0BC645D83D4664F59D4 /* NMBStringify.m in Sources */ = {isa = PBXBuildFile; fileRef = E857B5F6FE5852F628633EEF148CF32D /* NMBStringify.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 128EC9B7A22F98C84D1ED77021E59862 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 607DBEB86A79A5476B63B37A8059F2AA /* QCKDSL.m */; }; - 12D80FBF10D3D3A517689E9CABD6E77E /* RLMUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AB2EFDA17A907E630213AEDF7F8A7C1 /* RLMUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 14073D5591E42EFF0B535DBC24DC8F71 /* SDImageCacheConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ACC5157986C4C2A2BDDEE70753BE4B /* SDImageCacheConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1527F0D2E4CE817D3F98AB2EC0C25AC0 /* sync_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 285950CBD7CBC55792C73CA9492F7EA7 /* sync_file.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 1572B541D2F6CA85B39FEEC1F633287B /* ObjectSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = E410D4DEBDC4874F18B3D7909C7A1696 /* ObjectSchema.swift */; }; - 166B53AE7422AE81185DE33BA4B1DADF /* RLMRealmConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = D2DBF88CB3F9FA28E0C8002374D860DA /* RLMRealmConfiguration.h */; }; - 16A2ABB2ABFD2D206A5D1EF68B4B2FA4 /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AD26234BEAE0119C20BE4064E6D1967 /* Reachability.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 16DCB2F5C3B506867F812C6113E41144 /* DynamicProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42C961D3D18E87840C227EBD1663227 /* DynamicProperty.swift */; }; - 16F1E7F21615E00D010072C8F54DE3A1 /* UIGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49316E992C1B0F07E808EDF3EC85A13 /* UIGestureRecognizer.swift */; }; - 17261E344C2027602431A636759AC7F2 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E0BBF837B9CC5EDE662153D4FED782F /* DSL.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 185D2B0AF8D9889A2B17F9369C1D6441 /* RLMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 9397232493D47E251FCD38B034EF4755 /* RLMObject.h */; }; - 189050F5E247546A7641BFF083AFBBE3 /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607BD729441875C853ABD98B412B2F7 /* FoundationExtensions.swift */; }; - 1A0790CA03A6E9E3D8377F2FBB69BD4B /* RLMSyncManager.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = CFCCDC4D7CE01D0325D2BFC246BDD146 /* RLMSyncManager.h */; }; - 1A35C22776FBFD302E2325C331066FE8 /* MarshalDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC1470EB12CB6AAD6CC04DF5CDF56D7 /* MarshalDictionary.swift */; }; - 1A99ECCFD665C81328E2C765A7853257 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 1AE1445122691B48ED0D8DB61547E97C /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963BB70A82BFE7020C9EC5647DD540FC /* Example.swift */; }; - 1BC29B0D30BA334F7966E56D0415A3DA /* MarshaledObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63A2CD4F2A7F04523574F9DD1199A3C /* MarshaledObject.swift */; }; - 1C4E3E98C861706366D9F74A6417AEBF /* RLMSyncPermissionChange_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9219C02824374A414928D9E2AC846ACF /* RLMSyncPermissionChange_Private.h */; }; - 1C50F54510D5C2B2AD84D7B74A6EDEBB /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF52EE8C39F2294F4B0E818DD7228A29 /* BeGreaterThanOrEqualTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 1C563FEA1A1D3D29C5C41377CEC9037C /* RLMObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 31EA30FAB5AC797914D7B7A65FDF520D /* RLMObjectStore.h */; }; - 1C7CA1FAFBF8B865596C739FEA39CDEE /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = FAD121BAA02D2C889D46657A71F70ACE /* DSL.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 1CB81E6E538AD7ABC22241F8C8847AE4 /* UIProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AA0A291C2F56AA20159C8593C7CDF27 /* UIProgressView.swift */; }; - 1D04712344F8AFBC84FB2FC413198ED6 /* DelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA20BBD149564311AB716616EA39EEA6 /* DelegateProxy.swift */; }; - 1D1164642304C652C09F526994329A84 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB81A8BB2D4920F81288AE7615EA7AC1 /* ExampleMetadata.swift */; }; - 1D62A79936A0BFA068ACED23D6091C6D /* RLMSyncSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = 82D2257099413C297FBE7E94B01F5DEA /* RLMSyncSession.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 1DF1AC537F76166AB870A75A5154E3DF /* RLMArray_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E1CDE383243D554B0D7CDF7F0A56864 /* RLMArray_Private.h */; }; - 1E1C5FF6738CEB5F32C403EFAB295065 /* UIStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D5E0D36BF6CBA6279636E425EA8DD3 /* UIStepper.swift */; }; - 1ECC7B032BB9DBD2F63AC868DC5E823D /* RLMRealm.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F3E162DF05333F41599C41E7EA11AC /* RLMRealm.h */; }; - 1F3FDD37763AE6B26320B1E99269233F /* RLMSyncConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = BDB9157B69478671E392C9CF309B1BBD /* RLMSyncConfiguration.h */; }; - 211BA0ADE37913AA85C1E5FD52370C64 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC5C6C2D5404C2EA7B3C1FE285AD756 /* Realm.framework */; }; - 229D61E83268F1981C491E27FA4429DD /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F00AD52E5921222022AFA34B7A9381CF /* QuickConfiguration.m */; }; - 22C1DE74D494C10BBE727F239A68447D /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EA57594A19435F5B4B1409AB307B27A /* ThrowError.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 234BFC45ACAC4A8FB945EA17B6A74B0B /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7097638BF5C5369199675574769441C3 /* SourceLocation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 23B45D711EBC45C776AA84A54AD3A0FE /* RLMObjectSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 85FB91F281737568C40E1BE91EC624BE /* RLMObjectSchema.h */; }; - 23E2E1E02FE79EE1E1688CBBAA777297 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F415CC75AC70334E315CAA5786E84027 /* MatcherProtocols.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 23E386D2F3424DB21F3B744ED455CA96 /* RLMSyncSessionRefreshHandle.mm in Sources */ = {isa = PBXBuildFile; fileRef = C965627E2D5F1E9A4CF94AD8CEC1A480 /* RLMSyncSessionRefreshHandle.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 24445E61E879CF9258A59A745939A35D /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1215503EE4CF7889907BA3EF98947F5 /* ResultProtocol.swift */; }; - 24EF979DB6A2B88464E07F5C5937EE14 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 2705B708FF1C570FF972261A787F4D8A /* RLMListBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A6D3216BE419DC5864B02E6F2201C034 /* RLMListBase.h */; }; - 27B262F95D3CF9E3C74541A41929691C /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = C5AD5CA181843E2D59C76185F9F9166A /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2871AFC5EFBA6ED866C11164DAA12A62 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = E791635096951BE0C0F2A896763547E6 /* Error.swift */; }; - 294038CA8C05DBD13E34F40A0669815D /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340AC7AA1430E9A4AE03BE7D3FF434A2 /* Util.swift */; }; - 2969819001B203B84C76FB719B7CA2F7 /* sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3542FF4AD25D943D1E8DA607A35A7453 /* sequence.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 2B349866D9AAFD37E568AD026CD88B91 /* HooksPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA8B42E70E3399E2D9030DDA7AB81DF1 /* HooksPhase.swift */; }; - 2BC0D6FA54DD74A454031FEDEC31BC60 /* UISwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19ECB52F60624E4635D8091C15D6B9E1 /* UISwitch.swift */; }; - 2C26E0D45E4B6A28AFA45D3EAC8ADA90 /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 83DA572BDB4AE6A871F42422970968DC /* RLMRealmConfiguration+Sync.h */; }; - 2F71D099122CBEF95A180D0C20918DBB /* UIImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = C473DA61E0BF8FC1FA2051931C41EDDE /* UIImageView+WebCache.m */; }; - 3080659C90D5328E41FE5FF659F325A8 /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66A50B6824BF89D3C2F70DBAB43184CA /* Reachability.framework */; }; - 3169D990CA17FD66CC91665888341184 /* RLMSyncPermissionChange.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE76D1DE6FC0A51387FEF2D10B199EC /* RLMSyncPermissionChange.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 33F9866278D0CE3228BB9DD34FEFFBD3 /* RLMObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C60070B0166160719DDB8E19B9F5462 /* RLMObject.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 33FF2FB35C214948E64A213CCF3DBBC5 /* RLMArray.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3BE1B17FB3D1786D4AE6C6793272FD66 /* RLMArray.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 3424901DFFB13F114782634415ED1E45 /* Unmarshaling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9329FB7EF8E0C35A84BFAB0448E91888 /* Unmarshaling.swift */; }; - 343FC11494AC031FD071A2B978881A02 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7BEE7345BAAC8C6F0C4171128F4B21 /* Result.framework */; }; - 348354BC0AA067669E3F51E032DA8469 /* Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = D887D2D35CA24443E4491D8AB9ABF431 /* Sync.swift */; }; - 3537DDF9A83CA1483C81D408C0EE2FEE /* RLMArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 67DB0CBF7F97920F9ABEFC7BC7BE9DA3 /* RLMArray.h */; }; - 3548E948AEF451B2F781CCD0D199503E /* SwiftVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394D5A2846811D4CBC5ECA82A735FF30 /* SwiftVersion.swift */; }; - 35B1B0B2781D07903BFEA1C0A76F2302 /* ObjC+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACF671AF68F0FF123F51158EB8C2033 /* ObjC+Constants.swift */; }; - 35CAAAB3D054631676638C0D526C364F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 367692E23AA98BB10DB933E05955647D /* RLMObjectBase_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B9E00A2ADFC7E032F45885B40B5822 /* RLMObjectBase_Dynamic.h */; }; - 37220ED6E18CD75B6957A68B8D8FC702 /* RLMSyncUtil_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0ADA20B5CF9E864675679D4999BF006D /* RLMSyncUtil_Private.h */; }; - 3915DBB4731CB17B255A7FE86E240B6E /* CwlCatchBadInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A979E39ECA440AAF10D35FD95D0108 /* CwlCatchBadInstruction.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 39361705F2A05FB0C6860DB744A9481A /* RLMProperty.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 7933A983C1B0B4BC46FB1FC2C3BDDD66 /* RLMProperty.h */; }; - 3975A5075A67CBD8BDF04C69F64B2C7A /* RLMRealmConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = D2DBF88CB3F9FA28E0C8002374D860DA /* RLMRealmConfiguration.h */; }; - 3A698AFE74B42160CF93124938F698AF /* RLMPredicateUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = B382581DC6AB3FAD73955AE651D3AB2A /* RLMPredicateUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 3BA394A5178E534D4C9CD9325A3F862C /* Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2925EA57D3DED1B0B8C6F5FF019EE71E /* Migration.swift */; }; - 3BFDA793D5B648D0AB5CC863A73AD84C /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 059A2B4445E82FAF328D7F61095B3AFB /* weak_realm_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 3C06CFA9CE59B5A39FF7D9CCA1671DB8 /* results_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8004AF76C027BB4EBA37A5052DA1477C /* results_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 3C35ABB55635E4E969C2484133A3B4D2 /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB31B26BDDC740A81CB05AD0E163BDA /* Closures.swift */; }; - 3C3A1BEC07B413F36E7438CB932379F0 /* SortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48CCF27EDBE23C0E6EC0CA035D560C0 /* SortDescriptor.swift */; }; - 3CFE5F78A202A2878B8608C9869ED7DB /* NSBundle+CurrentTestBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10A6B890D72DD8FA3D51FA55D19A7045 /* NSBundle+CurrentTestBundle.swift */; }; - 3DA9FD766BBE43ABF268BDABB762F11F /* RLMSyncSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 3738F2E81E3C0A011D2B72D4A74BF811 /* RLMSyncSession.h */; }; - 3E42FF29784DB08DFBC8897C969F509C /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 319D47A4E04B1D1850D15617B34731FE /* format.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 3E66A0BD83BD5BE8D65AFB36D0942A5B /* ValidatingProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AAD639877DAE67319D9E59A0115D29F /* ValidatingProperty.swift */; }; - 3E99E7B06D279EA29C8F504614FC6072 /* ReactiveCocoa-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = BDE33B4567F08D97022ECC20CD08799C /* ReactiveCocoa-dummy.m */; }; - 3EE13A63F8E9ED7CFDB83235D6BAD4AC /* UIPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D25DB37DEC6459819431654AECC624A6 /* UIPickerView.swift */; }; - 3F156158393F8DC42F95948E071B69E6 /* RLMObjectStore.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 31EA30FAB5AC797914D7B7A65FDF520D /* RLMObjectStore.h */; }; - 4079D165294FC444BE339C0DF23813B4 /* RLMResults.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D0F4809D8692C621FA463BF89809892 /* RLMResults.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 40F6622927E23BBD26FABDD3E7108480 /* SDWebImagePrefetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDFBDC4BDF1483CA04B98A0A2778B67 /* SDWebImagePrefetcher.m */; }; - 414FF843979F8BD7EC6A8317420B3557 /* ValueType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797DA5F71FF30F1F36CB728EA07D86CE /* ValueType.swift */; }; - 4184EA6C9F7A5553278813C127F51795 /* SDWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 12254A6FC014605B8F73CD71E05E2820 /* SDWebImage-dummy.m */; }; - 41FF3B3A5D18846BD250B1D075DC0764 /* NSObject+Association.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5E84A9ECBA5E9CBA363FABBCB4BAE00 /* NSObject+Association.swift */; }; - 424AD01825E6B0836BB7EB22C5D023C7 /* Decoded.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CB2E5C87615DE8B3C12CD9493C9868 /* Decoded.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 42949F801C0D3D6B7A45049A2AA1F82E /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2225060BAB6998F7631BB9AE0B59981B /* UIImage+MultiFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 429CBF05F23D7C892F041950B40B34B0 /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = BFBCA3AA47952AF10E6F190ED5CDE623 /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 42B8CC75C2318A9B48B66D996C478CAD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 4391EE2ECE3BA2786D86DA86C00C2AF8 /* NSObject+Synchronizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4817823CC44D88678A94F02F15DE1CC /* NSObject+Synchronizing.swift */; }; - 448ADC334870B554FF36A8B7A44E5FA3 /* RLMObjectBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 588716E07AB61E12616DE68E22140115 /* RLMObjectBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 45C4C7AE020F6045F18ECC1480A8B429 /* RLMRealmConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1FC4B0E456455B6FA693C53B90618F36 /* RLMRealmConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 465A6D3A81AF9DF432D879D5813EBB13 /* ObjC+RuntimeSubclassing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E797468E6591915891B2AC36BAB076C0 /* ObjC+RuntimeSubclassing.swift */; }; - 469E2AD072EB9A7ED6E43929375E961B /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8A2A2A21C0F8A5BE916EDDCE782ED2 /* ReactiveCocoa.framework */; }; - 469E9C3ED9FD6009F7C9AAF9E537E212 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 05310AA14FB2E89FACDD353E85A90C83 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4832ADCFB52202045E43A4BF8FF60678 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C09657AF9A1B91C4D3AEDB678B9BEAD0 /* RLMRealmConfiguration_Private.h */; }; - 48C2D1A7CA70E0705BAAC5825543C696 /* RLMMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = DF14F4BCFCB54C50CC44B9F24A1C06E0 /* RLMMigration.h */; }; - 49D5208D5BADCB6F1C2B5BA95C348E4F /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D8A7566C6856373259F87570F1D754 /* DSL.swift */; }; - 49F1E2D496CDB97D6149B190BF1E711D /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9CE6DD770779A4EE2956B3364C4D86 /* JSON.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 4B2A28C3B7D8196D0D668639EF054A00 /* RLMNetworkClient.m in Sources */ = {isa = PBXBuildFile; fileRef = CC5BAA85DDD9939DB814BBEB2EEA6B00 /* RLMNetworkClient.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 4BD582A689CB31F53ADAF1C676E9608F /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF2759610C450FD80023B3565046245D /* Bag.swift */; }; - 4C2E161BCF00CED28660CE7130DE6A83 /* RLMSyncPermissionChange_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 9219C02824374A414928D9E2AC846ACF /* RLMSyncPermissionChange_Private.h */; }; - 4C3F2133B6F3A58301106A9F79A75ABC /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8C403E25985E9B3F49A7D80B55B8F /* EventLogger.swift */; }; - 4C7DBD5B1AB61B1BEDBEB1323EBE7317 /* RLMArray_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 0E1CDE383243D554B0D7CDF7F0A56864 /* RLMArray_Private.h */; }; - 4D71AED5656A253602B5F29929E906DB /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8069B37F697707BB94630A7CFF7465E3 /* Disposable.swift */; }; - 4D744EF8A360A1389BCD8DF0B6FC0273 /* RLMSyncConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = BDB9157B69478671E392C9CF309B1BBD /* RLMSyncConfiguration.h */; }; - 4D98988A627FC32461D79A732C4349BC /* RLMAccessor.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = A901B8CEB82AF015D61F999D5A7E8D71 /* RLMAccessor.h */; }; - 4DA99736E2B23EE647F695A3AAE4F693 /* SDWebImage+RAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4006BC04F14AE7E96891627AAA66B46A /* SDWebImage+RAC.swift */; }; - 4ECC3799B8C8CFED57C4B1F8B853D452 /* sync_metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 803396491622E4B64777359DFE9C44FB /* sync_metadata.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 4F329464CFE2D937CBA77A6CAD12054D /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CFBECA7EDBB969B477538958A4E4B2D /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4F3F103945CC52D0A3B8A891BB0E21C4 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4166BF3271091D2B727C28AA3921B51 /* RaisesException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 508B92FDF4F2433D03CA6CFF5F0CF8E1 /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0022F7705FB317525EB64D8310D6EA4E /* UIView+WebCacheOperation.m */; }; - 50B80F12A9BAE302F07F6CF94752F462 /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9303ABBB4DD1AC4EFC6B839FB06EA148 /* mach_excServer.c */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 526108C6389FA50A8FDC228DFD8D0A47 /* UITextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 334F857F93FC618C80B8306EA8C02F03 /* UITextField.swift */; }; - 52F86970C84888E35702F50A03E6BC74 /* RLMListBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = A6D3216BE419DC5864B02E6F2201C034 /* RLMListBase.h */; }; - 53F32D934AD582642EACF4374DEA778B /* SDWebImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 6508E193CF684DA6CB3E037900D61985 /* SDWebImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 54436A6669617C2D975F8917FFE99E2C /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AE0F8E56CD72C260B37D78AB6061F35F /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m */; }; - 54E5A7DF676BB926250CABA6CB61CA6A /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 126814190611329563A399525B529E45 /* SDWebImageCompat.m */; }; - 551440A0F92574039C1D2EB39227D6B8 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7105FDADD9F5EA077FCF4AB41527F29A /* AsyncMatcherWrapper.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 56600FE41D89E6F6B1A4953A4CEFF64C /* RLMSyncUser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 01D68A2A4CAE81125EC2676085493945 /* RLMSyncUser.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 5702A743E24EF86F57C079C53994AB8D /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = BACBB011CA1C6A70A56074BE121474A3 /* Atomic.swift */; }; - 57388C6C2B3C17F76EA25EA39EE42B6F /* Reachability-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B736AFE30B4A49758F137F1A60E57887 /* Reachability-dummy.m */; }; - 574C9B986CB151FB26A5FB44CD79149A /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A6343B009137DD1A99C70E4FEDC837E3 /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 57CAC2857F0D32AE17917EDC5B218CFD /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7750B0A880CBB6D5D731191421BC46FF /* Object.swift */; }; - 5870697EACB3585E86BCF13330B093FD /* Realm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01060E818490024E600D55519EB092E1 /* Realm.swift */; }; - 599669823A2EED2928C77F301F6B0515 /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B16B462FDEFE1759C0D8EAE416E19E /* BeNil.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 599BD31B967ACF5D5E1ABC57E79065E9 /* TupleExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5FCFC7C955830E67FEC0C8844B49590 /* TupleExtensions.swift */; }; - 5A41AC00D39F27E8B0124ACAC8528442 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 5ACF7DF166DDDA521C5905D11EFB19E6 /* Applicative.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B4D6BE656A53B5B57D0BFB9B020A68 /* Applicative.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 5B4BC0368196FADEE78A134EFB3717FF /* UnmarshalingWithContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 392220F412D83DABB8377C6A3546887B /* UnmarshalingWithContext.swift */; }; - 5C1C2E5A285203E728D90731DFD3C433 /* RLMSyncCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = AC9EF25517ED5300468609A48031872D /* RLMSyncCredentials.h */; }; - 5C593FC7DC74D282A26500CB15613CDD /* RLMObjectBase.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9436789E37E80359F8A2176F388D3B /* RLMObjectBase.h */; }; - 5C96F2C33890F43BD0CFD19D9B656AE1 /* RLMSyncPermissionChange.h in Headers */ = {isa = PBXBuildFile; fileRef = F27228CB12B965FDC0DD1256B8843676 /* RLMSyncPermissionChange.h */; }; - 5CDD399EB240116080FD072259A77F01 /* NSObject+BindingTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5030F477E12364AAE5532F5BE20AE54E /* NSObject+BindingTarget.swift */; }; - 5D8E324A5B6F5DF8A988DBF19B8BB81C /* RLMQueryUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = A7DDC7C79747E06F695CFE767BF514FC /* RLMQueryUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 5E7520F9D135C952654E24FF28398EA6 /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = A1037624D3A582BEEB81981869141420 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5EF329BF99862C62938AB788669BE8AF /* UIBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0412A85F1E6549BEDB139D20B1ED081B /* UIBarButtonItem.swift */; }; - 5F138050A5C0C08631AE1C299A6E9057 /* RLMSyncCredentials.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = AC9EF25517ED5300468609A48031872D /* RLMSyncCredentials.h */; }; - 5F85FA3B4239C013EC015B225A8405D4 /* RLMListBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02C9F75B74BA0614F8A1E06E422F7303 /* RLMListBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 5FFA9972AFA7207AB186A112CC6B1641 /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AB32EFA3403D705D88D68795CBFACA /* Scheduler.swift */; }; - 6007DADE9D72350EEDDCC3C826D27698 /* StandardTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8973670C4D50F686E0A23EC6A97FBA02 /* StandardTypes.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 6164192DED4986BA2338CD392AB24845 /* ReactiveCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E16D1C7108C92F7132BFE96188F7AD2 /* ReactiveCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62426F69BA1918E570C08AED191EF40F /* RLMSyncConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C2123A0484B67CA9CC476814C0120E75 /* RLMSyncConfiguration_Private.h */; }; - 62744EF299751FB49B5FCD81D8C8FFF7 /* SatisfyAnyOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = E558444A08D66A43ACA92FF003508D39 /* SatisfyAnyOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 632CF89DA882625AEB0F3A7EAB7F1653 /* UIKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F5AA65BC44CDE9194A8836CB27C67B /* UIKeyboard.swift */; }; - 638A4E4B18F6E5A359B5F2B8FF231FB8 /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52653314A619A2302BEDBD734F4F9F36 /* results.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 642C154875522E8ABAA04FB28C6CB1BC /* CocoaTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 718DF05EBBCB9BDE444E6A5537C11253 /* CocoaTarget.swift */; }; - 6486FF457E5C3F122BC98A4DD7B80CE8 /* Realm.h in Headers */ = {isa = PBXBuildFile; fileRef = C83184A660ADDBE83E50CB93257B58CD /* Realm.h */; }; - 64A16CB7A74E20B810FE6D7879935961 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 64D6D3C4C06DEE74FCAEF12A9810BA1D /* RLMSyncUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = F10F672222BE731F7EBA1ED547D8457A /* RLMSyncUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 65F5217D44A557FC16218DE5DE348C35 /* CwlCatchBadInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B1AC27116D413175DD38E2EDF04552C /* CwlCatchBadInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6697CB49966B6CB66C382EFEDBE664D8 /* RealmSwift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 12612EF0C0D0DB42DA16F98083C20B82 /* RealmSwift-dummy.m */; }; - 6793F92D394368B5122346D40A26AF5D /* Runes-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 404FFFD3541475853E542117FD585D0C /* Runes-dummy.m */; }; - 67C9D041D08BD84FD7A7AB830FE94F39 /* RLMObject_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D48FF7D6643A2CA2A68C1C44D2E1C5C8 /* RLMObject_Private.h */; }; - 6812F52EC81468AD671295EDA4C068D2 /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = F487F50FEA89C151AF2484ECACBFDD60 /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6860A472B8C0EDF4C3FE12596E9A9DB3 /* UIView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A347A88FAFBC3EF3A8473E08354ADC1E /* UIView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 686CD02C78B4819E0D90F8A2FBFC4F12 /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8D78E35B6799FBE72ED77EF444B26F /* object_schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 68B5ABB6BDACDAB1E40F37BFF234B2EA /* NSString+QCKSelectorName.m in Sources */ = {isa = PBXBuildFile; fileRef = 76E1482324EF76467354EBCD9556D5C3 /* NSString+QCKSelectorName.m */; }; - 6974BCB4113383F63F4D654F60D97AC9 /* RLMTokenModels.m in Sources */ = {isa = PBXBuildFile; fileRef = E3C38B9CEA209FE6C7811DF0EC3A1BA1 /* RLMTokenModels.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 69CCDEC9F7B1E7077F24A57310AEB40F /* flatReduce.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F4C0E290ADB2B3B26394BA66CA4385 /* flatReduce.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 6A9B5F2E706D55A69C6A5E2754A97B2C /* Alternative.swift in Sources */ = {isa = PBXBuildFile; fileRef = 721752886DA62F718878703E4387C37B /* Alternative.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 6AADE869DC160B2B1DEAEB77B7E474F5 /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4B1E8C437B59066AD9B23630A086B09 /* schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 6AE97685B60446A4640646D889EE099C /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = F737531120822D2EF585EEFF24764A32 /* Operators.swift */; }; - 6B54C8A8B1F68CD253E26A8845C994AB /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2F719B9B7093A7E3611B4CBA6D4BD44 /* list.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 6B8D25E891A0511F86A5A37D5570D85A /* Reactive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C829B3ED1CE47110FB4243A4AA1DD0 /* Reactive.swift */; }; - 6BAA81150FFC0127929E1734953C1EBD /* RLMUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 564DF2424B8E212FED546E5CF3D4DEC9 /* RLMUpdateChecker.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 6BB08C533B9F31BB8C8BF1DD2395E3B9 /* Pods-ACKReactiveExtensions_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 712808AA58D0CF2BE85538F15BA355BB /* Pods-ACKReactiveExtensions_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6BC45F532D80B5E2CA7994DAC5F991E1 /* DecodeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6400103CC33210C1B50120D98BE83F0 /* DecodeError.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 6CAE17DF3C4F68FE927E58429FC22D4E /* ArgoMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6239884AFE3DC00BD7C49C2EFD25B46 /* ArgoMapping.swift */; }; - 6CDBA48C3A8621E4EE1DAFFE240F0D82 /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A4BD9BF1A83C0E6C3FABF55C75DC471 /* CwlCatchBadInstruction.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 6E397D9FB11A47E48D70287D734B12B2 /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF5A0E74BE0C0E430EE089E1795F92EC /* BeLessThan.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 6EA2E0EB06FEA7B3B78DCF8703E5BBC6 /* Marshal-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 49D6560115C7B2BC53A70882B073C3B1 /* Marshal-dummy.m */; }; - 6F4B3812DD04451FC89150E11156113D /* UIKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C8CFCE00F3EBFB11B577E7C8AFD9BA /* UIKitExtensions.swift */; }; - 6F5627AEEF49A667AD9398805AE5038A /* SDWebImageDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 107AA785555CE6CCC4A8F3E2890C4499 /* SDWebImageDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6F7010E2A68AF250CB9432AF99700979 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7491821E2D46EE33A835436948D1D049 /* Reachability.m */; }; - 6FED3CF3C073928BBAFD13BE61270D6D /* QuickTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47E6B078EDD964EAC0106763ABCCCE4 /* QuickTestSuite.swift */; }; - 707877BCC4E5F20581E5ADEF4C4ADE4E /* ACKReactiveExtensions-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 991B28D558F7F4AB0752F5EDF23FEE75 /* ACKReactiveExtensions-dummy.m */; }; - 70A80DDEE055E28E0C3D4E1EBC53305E /* UIScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7222A864F00CCFD6624F1E635745EF2F /* UIScrollView.swift */; }; - 70DAF19A0935877A3A8110FF0E6C5BA8 /* RLMRealm_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F4C34DBECC5FC8CDC1A5D97DFC0095A /* RLMRealm_Private.h */; }; - 719D27143139E827ED71B4EA147F1AEE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 71B113AB3D0C0DEFAEF9A32F75753EA7 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = E6D9E3AF330175AA70AFDF06735E8B8D /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 72630AA3A5D8D8F5DA055ECC19B98B58 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF22416A2052DCD719780514C43D7DD3 /* SystemConfiguration.framework */; }; - 72EB734BAA053E4F3A2830445325CA18 /* ObjC+Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED9810E50E8D4C73D14E85A64344E59 /* ObjC+Runtime.swift */; }; - 72FF59DB723E0F2E89396B5A9687F045 /* Argo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E00F5ECCFE503D51297AAAC62731DB3F /* Argo-dummy.m */; }; - 730AE4DFA1C9E6C98D5E9FB3AFA48821 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 20ED7AED4F9DC9FD6F9AA9B59F0EDD83 /* XCTestSuite+QuickTestSuiteBuilder.m */; }; - 737E19F3254F5929263982C29237C0BA /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583DFEF3167808DBE921F927EC0647D5 /* CwlBadInstructionException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 74147EAF25F637C65E7E35965E1F5EA7 /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DB2110822BD1008D595EA83C92482309 /* UIImageView+HighlightedWebCache.m */; }; - 7476842145151214CB47BFF8EB617702 /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05D6C2456AFE9C400319370C741B2E60 /* World+DSL.swift */; }; - 74FD712F3B503891B6BD9E5CD287E481 /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DF3E05F9FFAE9E02C11FE84296F7A20 /* AssertionDispatcher.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 75171AF1BDA20F22D864641F10968785 /* RLMSyncErrorResponseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 64D4DAB0875793978F8CC3CBFADBCC0D /* RLMSyncErrorResponseModel.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 75A9698B3E524A3AE1366AFB798A64E4 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = E083C71019FF77A198A3A5B6729E9C16 /* Deprecations+Removals.swift */; }; - 75D3BE7F259395437A39A41B3B3F05AE /* ACKReactiveExtensions-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CB229C70353D865CBCDCD994B056AA /* ACKReactiveExtensions-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 76036D32625A56D480D84AA46961EF91 /* Nimble-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F41849D4EFEC7E703EE4C478513EEBE1 /* Nimble-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 760BAF96082DD5B6A743284629EC3308 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15927EE2028CAB56CFB99EF18090C7CF /* World.swift */; }; - 766C0FF607A75C9CED8800DC806DD5A0 /* RLMSyncUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DC1BCD07008B3D42C609AE5328DCB8C /* RLMSyncUtil.h */; }; - 7726D1D45318323E9B1412DF0F5C9D37 /* CocoaAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72897D5228D7E9D0CA2BCF625481E0D /* CocoaAction.swift */; }; - 77482810CAF896DC6876023C1362122E /* UIBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76B8505276FA8CA680C74C2BF1FE31C /* UIBarItem.swift */; }; - 7810F7BA08E09A3CBA4ACA5B752E8627 /* Functor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7335FCB18987188E521D2CB4729E488B /* Functor.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 78402B1C5038AE832D93BF4C3B56766F /* ObjectiveCSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 206E1E12150B32DB317DA4656D2D26AE /* ObjectiveCSupport.swift */; }; - 78D42446501980211659468501F92508 /* RLMSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 979DECF18FE73967EBA41B3938401CA8 /* RLMSchema.h */; }; - 78E1ED7C0CDBB76BAEBBDA0491CF4AC0 /* Reachability-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C92847251E673E2C9A4421274F02A9C /* Reachability-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 78F3DE174B4F8D368EF8EEFD7EE62087 /* BeVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39424FC5D2544CC107EC61D28A83CF56 /* BeVoid.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 7940DF18814F9321178EC538E43BA409 /* SDImageCacheConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 3282A40C35AC3A6009A27E7C2E672D10 /* SDImageCacheConfig.m */; }; - 799BF35B297C38560B206DA38DBC1BC2 /* RLMPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 966BAD0CEA9341185E138C46BDC13777 /* RLMPlatform.h */; }; - 7A4CD8BE858355870E06DB4D9EC4C5A4 /* RLMObjectBase_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 13B9E00A2ADFC7E032F45885B40B5822 /* RLMObjectBase_Dynamic.h */; }; - 7A59C0B01342E690DAA6A63054D5B1FA /* NSObject+KeyValueObserving.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232FC4E435DA00B8472D3DBBB13915A8 /* NSObject+KeyValueObserving.swift */; }; - 7A855F80FA047F2B1921E7A0710DB4B4 /* RLMAccessor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0A006DAB665D087A81363738F07BB8F8 /* RLMAccessor.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 7AE0746CCA5D2EFB3CE4DD703DB8207E /* Deprecations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9447ABB644366BA6F61BEF379830782A /* Deprecations.swift */; }; - 7B957962DCE07FF50BA1011DE56C727B /* NSNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5F32DF751D97190D3F56A0809955BAC /* NSNumber.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 7BBB202F4A3A235566C2146CEE813C48 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 7BE5AB45B8861E689B7D3F1434A4873A /* RLMSyncCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD9C8DAF1108DFF164034DBD5137A01 /* RLMSyncCredentials.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 7CE3CE78117685C574CDBC1059E93B95 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8907DBAC4A353CD157422CC1361BE27 /* Array.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 7CF1C8A268B9FB75788C1A2E42FDDD87 /* Results.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47D7EF3D5D559122CEC7B8050B62E114 /* Results.swift */; }; - 7D6269A3CFE53C28DAA6B92E8FC017A7 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69521AAD7D6505125DEA62C9B1AC7B2A /* FailureMessage.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 7D696B3DF6E33D44478F2A794B82E44C /* RLMMigration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 59AC20E6AC41358A4AE618014B5DE572 /* RLMMigration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 7F6750C7B1847733370B18C4CBFE32DF /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FBA9589FAAE69C553734B593FEB496 /* Errors.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 7FB2ECBEAC0D5F93B278A7F58F168D4B /* MarshalMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A516F7D84ED85B2E9DECFBB69017DDD1 /* MarshalMapping.swift */; }; - 8015239010C1D642F14C105F8FF8E035 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEE75D737864E8B717EE9DAC08740CF /* Expression.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 806B25F17A7AED6E1C53A7CD7B909B16 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 81250C24C643652A242941C6904077B3 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE65A0CE34A217C207333F15D71AB4 /* UITableView.swift */; }; - 8186F1339FA8E4E69A2A53038C96CABA /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = 555BC55AF5CF61AC1064B2BA8B77D5B9 /* World.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 81CC62CF8A1AD74849A246741DD9A8AE /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E89418684BB6D4571366C9D27F6AAE /* Callsite.swift */; }; - 821321102B29CAA5C96FE391283425FB /* UIRefreshControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512B9A5158A40CEC213006BE06F53315 /* UIRefreshControl.swift */; }; - 82D1F822758EB03CD479943CA30D5A38 /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAE2BA55456042322852F0EBA66E3E2 /* ExampleGroup.swift */; }; - 83030E8C22928BB6014799EAFA54BEDC /* RLMOptionalBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = AEDF0E9F5960B84839C674C69004405F /* RLMOptionalBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 842A7A8A9CE04F6991A5231C56683469 /* RLMSyncUser.h in Headers */ = {isa = PBXBuildFile; fileRef = B4DB6173F603EAE2C38283B1018FE1AD /* RLMSyncUser.h */; }; - 84A77035E531CBEA183F49DA69CA7988 /* Realm-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 59D6B728F4B5D6683F3879D7DDA63938 /* Realm-dummy.m */; }; - 8507F4BF7437EB40A3626EDCC68BFF6D /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54DA9444F1ED16C10D04D55654096038 /* Contain.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 855E10DB10F413F8CF85BDBF88648566 /* RLMResults_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = E48EF4343180C760186C4E41CAD7F000 /* RLMResults_Private.h */; }; - 85FF8757FD497275E89406C1A645DB3C /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4F78E60DAA32E09751420F5C65B9F77D /* collection_change_builder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 8654571F855691C23B7B8E61B2141944 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9DF474F5F5E99E4053356B4C5495B51 /* EndWith.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 86FFB76B2EDCF4AE79CC4C0BD8A0FE9A /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8908482E11690C4B6D21DFDDF4B4A9 /* DSL+Wait.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 877D85263043DFE712C617A0C59365A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - 87DD62F200DAB5E1D701AB9F94D1D422 /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E033FD8AF63521D07649FF36BA00D05 /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 886E986B10F6FA5D0F6C61148C219389 /* RLMRealmConfiguration+Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DA572BDB4AE6A871F42422970968DC /* RLMRealmConfiguration+Sync.h */; }; - 88908549852319C0587D5DC59ABF542F /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D3882CC443D7C99789F1CE6D7CA7975 /* UILabel.swift */; }; - 88A62885EEF84639E1377060A8CCAFCD /* RLMMigration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = DF14F4BCFCB54C50CC44B9F24A1C06E0 /* RLMMigration.h */; }; - 88F7FB6C300DF156A17FD60E4DFE52B4 /* Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88FCD6FA8617AC21FC97DBD75A967F5A /* Decodable.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 8BECFAB439E0E23A0788E73819FD0C99 /* collection_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE07F2CED458B99C1A99A2A00AADF567 /* collection_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 8C30EAD5FFD28B387099B41C74657A67 /* NMBExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E46BEDB9FE2948BDB0C0A8EC1E43306 /* NMBExpectation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 8D1CF1C8C947F820AAFFC6FCC5E3A641 /* NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4E14923BB45C7CE2295CAD3C4D2A0A /* NSLayoutConstraint.swift */; }; - 8D52275A90F68E5056410E02CDCF7A56 /* Result-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C3D20A0139A53C62A3196A015F501A35 /* Result-dummy.m */; }; - 8D5AFB85F283F350E04DCF8F39ED65BA /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = D06DCE506336E68E74741682FA232A62 /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8EAC470AC832E141796F9D59C5C2F962 /* SDWebImage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D636D627BCC9BA5B12D79DD65E7E7E63 /* SDWebImage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FDAF52E5935BEF09109C8F8882CBDEF /* SDWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AACEA0B58AD6F1E95023ABD1DB5262F2 /* SDWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 917949F596E1188261FC59214782C3D9 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE4CFE17744FA0B4EE48863BB8E6C0C /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 92AA67627EDA0B84C60D259D54C7ED60 /* UIDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B3AA4360B79AA046AAE078E12F3DFFC /* UIDatePicker.swift */; }; - 940ECA327E68E6CBA664C18A2C621317 /* RLMResults.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 1EF18CB021556D923160AE960C55D41F /* RLMResults.h */; }; - 945B452BF9ADFE70921027D1160F1484 /* NSObject+Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105FBA0BD89AFC25198AE4334E657AB6 /* NSObject+Lifetime.swift */; }; - 945EFCE55FCC4F5717B597E2B23340E6 /* RLMObject.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9397232493D47E251FCD38B034EF4755 /* RLMObject.h */; }; - 947162383483B6391F8CDF38249BFBD2 /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 597631411F419DF710CD14B247BB2214 /* CwlCatchException.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 9531D50971D4F3A23EE8B7D19536E351 /* RLMSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 979DECF18FE73967EBA41B3938401CA8 /* RLMSchema.h */; }; - 9544A4EEC2A8448743ECA9981F88B60F /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA1F5A214BB23FB8B82D8EF6A22A092 /* BeCloseTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 955E681529AFEA62705D90C06B60ABC9 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE4C4809982D8B2B4E0E32574AF0D2C /* Error.swift */; }; - 95EB0825E03A9821C7F55903F9F29273 /* ReusableComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788E044960791E209D43E3E6104BA2CC /* ReusableComponents.swift */; }; - 9619734C9DEDC0A052C29C9290ABEED5 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD64BEE47F7F882E962E75DEB7F825F /* JSON.swift */; }; - 96C9ACF2F8B533643E5ED7123E4AEF88 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 915588B75D0D58472F979621CB7066B7 /* Filter.swift */; }; - 973A4BEBA2ED6C185DC98EA2E2EEF01B /* String+FileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05B079F9AD843FA9C72FF8899904B85 /* String+FileName.swift */; }; - 98080D71E255BAF41B14B5147F715D17 /* SDWebImageDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 50D246C696E1D1DDD1F8545492DE9F95 /* SDWebImageDecoder.m */; }; - 9873E590CEB5A8C377F67E455852F0CC /* KeyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1ABBE197ADEF9C7B459DCBAA0430C87 /* KeyType.swift */; }; - 9996C1F28B2CE2EF5B81DB9A9A6C7213 /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E32958826C878BB739499B7333715279 /* external_commit_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 9AF235C16362BA00BFBF12147907E953 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78D56E6C8D49BE35A469566AD3FB1761 /* BeEmpty.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 9B61BFAB089A491FD59D6FDD4A716F14 /* DecodeOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B463B62FF6326026FA653E42C9926D /* DecodeOperators.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - 9BEBD1791C233763A8DC13080BFB99C9 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037388FFAA7D6DD4BCFB36762737DC94 /* Stringers.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - 9C7EBA9F477CF43D497E502209360B14 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D10832EF3E35D8B927A00C7D9AD97AC7 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9C843F1B007EEE9E2E44BB04A9D45D6F /* SDWebImageDownloaderOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BD95C70957EA9EA4B65B2D724C34C0E /* SDWebImageDownloaderOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9CD91D90F932A086B01FBE19417A3424 /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53096508F660433426E57D71FA76C816 /* transact_log_handler.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - 9DDAA27C7BD1BC420D606A88F9949B58 /* ArgoDeprecations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 144962E04851A77F7F0ADE3855B9AC12 /* ArgoDeprecations.swift */; }; - 9E09AF4AB2B428CDD1B45CE39ADD6706 /* RACReachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ABC5D71A2A908186B87517B2A07A91B /* RACReachability.swift */; }; - 9E7A6B432FD9D03B8C2EC3180525177A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA1C3C2C9C97BC2CC36CC727B5A072D /* XCTest.framework */; }; - 9E95D6E15DBE9B0FC92AAF60D42D1464 /* Nimble-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AF09F3100D0F9E7D24B84A1BF0700FE1 /* Nimble-dummy.m */; }; - 9F70699ABA6AED4577F9C027EF572700 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95285970C9E3D84B94D81925791804BF /* SDWebImage.framework */; }; - 9FFE05121CBF14144F5F16B8F98B120E /* RLMRealm_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 9F4C34DBECC5FC8CDC1A5D97DFC0095A /* RLMRealm_Private.h */; }; - A042E4E8708798EE81C7EB2D7EE3C2B8 /* RLMSwiftSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = D7ADF689A2FEBF5D2B0B97224BE6E39A /* RLMSwiftSupport.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - A0B7FD0173B14EF31E5C16CB311128FC /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A4313403997D85BB033DC3CE9FE2DC9 /* SDImageCache.m */; }; - A0BC3C79604FEC79CBC351BC79EE52A8 /* RLMConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = CAD193490FD0DBB2F2D5487F16FECFCE /* RLMConstants.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - A0E4E8486CCDEC6710FD4649BFF1B515 /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2700DED06348763C77CC011CE6DB3AB2 /* Property.swift */; }; - A10F09E52A0AA09EDC77BF115B5CACD6 /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97500615959F3658229E0B487EA37835 /* realm_coordinator.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - A1E786FD32DC1326DCFAA2B8B29B35E2 /* object_store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5062007710E1BEE91B95001D87473D2 /* object_store.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - A1FA40A47007CABA456102535530AF1B /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E60902B8DF5048C387EC367747141F /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A27C038A5FB17B7A95CD328EEC66B37B /* RLMSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 33FD8512741E03356DC3075014CB736C /* RLMSchema_Private.h */; }; - A2F1066AA4D39EEA9EF3D52BE178549B /* LinkingObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C78D129BD75FF297820F1F1C73A7F6 /* LinkingObjects.swift */; }; - A33F1754198E8E8CCC7087F6176FFDC8 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0202A6056A7E85A9737903599CC8EA /* BeIdenticalTo.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - A369B6AB9AB7A60CAFBB3169832D18F8 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E72339A6F866D44B06A0DAABEBFC423F /* ReactiveSwift.framework */; }; - A428E7476E5AC5EFEA2407865C6BE9D9 /* RLMRealm_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6B4B4D235F8BAAE064E0DFCC37393113 /* RLMRealm_Dynamic.h */; }; - A448F837592E21D9387322E8DA0DD93F /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24BFF19FF08365F5A7A2FB97216ACCF /* BeAnInstanceOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - A5BFD1D307FC92CE1AFA6D049524D052 /* ResultExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D5719DF5A213B3338485A997A32CD31 /* ResultExtensions.swift */; }; - A5C0A3DF28C2B95FBA5F212D202817E3 /* Aliases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6B92C6B8D16F1B9375EFBB3DF874C5 /* Aliases.swift */; }; - A69E61CE8F3B0B58285AE941F5046C9C /* RLMConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 91BB85FE67400DD1B6A46E08596D0760 /* RLMConstants.h */; }; - A7581CA42D2413F98AF248137A827AA8 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D86207497AC6CFA632EC64CB15A5923F /* UIImageView.swift */; }; - A7E82B461C481EBEAA621278AFDF6101 /* Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314B8B6D64D349093EF3480BEE71626D /* Lifetime.swift */; }; - A89CBB749AD66074ED365475C492F511 /* RLMCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = F0EEE9DA2500490F96A921B7CBEA5293 /* RLMCollection.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - A8AC0FCECBBD879B6D59D1D151F16F46 /* UnmarshalUpdating.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC01834CF2177AD8BDE489FD5511D73F /* UnmarshalUpdating.swift */; }; - A91166D0A5E8F1D5D5377622C381C045 /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7008F7E5A7BC03218B8379B5924B5CAB /* Match.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - A9645EB788CD6208F3B7621866869B16 /* RLMProperty_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 4AC6B8BF65E2C5C0DB2344F42211B2AE /* RLMProperty_Private.h */; }; - A9FAD00B27400DC8EC15C440F098B5C0 /* RLMSyncSession.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 3738F2E81E3C0A011D2B72D4A74BF811 /* RLMSyncSession.h */; }; - AA5C81AC887E7F2A0875948D3D3972B9 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7BEE7345BAAC8C6F0C4171128F4B21 /* Result.framework */; }; - AB255C27EF10E742C6567775022F49D5 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6215008A04F973F0AE63DD326BD1C487 /* BeginWith.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - ABA98ABBFCF699BE733946CB737CE6B9 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A1D01AD61167F40E747F4BA875E5B4 /* UIControl.swift */; }; - AC0B24EF198E3BEDFCC9F25D7B8EEDAB /* NMBObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDC63EAB2558BED1B47A3463C271EF3 /* NMBObjCMatcher.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - AC29CC89E22273BF0D0DC2C841B7524C /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF28C6F7F43248012239061C17517C4F /* Async.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - AC638215CCCC7AE76B73DFD0AF915859 /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142256C1FF1580722ADF79BC64D3570C /* RawRepresentable.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - AC985DC0886CF01DD5FE23F6C5A5A316 /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1EDA68881B394DFBBE8D776E4FC50E /* Property.swift */; }; - AD07F70DF53E2C820D85F52F7564F001 /* UnidirectionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7087BC923ECE8A70F3168A6EF38FE9E4 /* UnidirectionalBinding.swift */; }; - AD8A2AE3E3391149462A67D784670F27 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - ADBC05DA5968674948A96809175229FF /* RLMSyncUtil.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9DC1BCD07008B3D42C609AE5328DCB8C /* RLMSyncUtil.h */; }; - AE5A2C5AD3EE2306BCDD6000AE71B929 /* RLMPlatform.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 966BAD0CEA9341185E138C46BDC13777 /* RLMPlatform.h */; }; - AEA36D26E43E510E6CE8D61593C95A2A /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E72339A6F866D44B06A0DAABEBFC423F /* ReactiveSwift.framework */; }; - B093484B1637B3D3AF65DF2232FDBADC /* mach_excServer.h in Headers */ = {isa = PBXBuildFile; fileRef = F3799C1205E4466C237F4B2CCA1AF7CB /* mach_excServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B0E4C731E1B85307EDDF547A51532016 /* RLMRealm.mm in Sources */ = {isa = PBXBuildFile; fileRef = CFBF2C669407931F2E961AB92AEA7F1D /* RLMRealm.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - B143EEE4F93C26829429C443540BF4D3 /* UISegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B82C0D57E8ED3BBF27CBF4EF355DA41 /* UISegmentedControl.swift */; }; - B17717D3BA6E567367D929686CAA194C /* RLMConstants.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 91BB85FE67400DD1B6A46E08596D0760 /* RLMConstants.h */; }; - B195B58E4827B58E91267521354F3F19 /* RLMObject_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = D48FF7D6643A2CA2A68C1C44D2E1C5C8 /* RLMObject_Private.h */; }; - B28A0FCD25DED5AA0B68E305638F5BA9 /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 915E2130F82FBCD696E7B41FD2255114 /* UIButton.swift */; }; - B3C6DC1ABA6D315DD8D6BC5A0F408BBE /* RLMResults.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF18CB021556D923160AE960C55D41F /* RLMResults.h */; }; - B3CC6C919614AA5981B0845892914191 /* RLMObjectSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A7A857A352C067C32F07E9DED5F857 /* RLMObjectSchema_Private.h */; }; - B503AF03D73353141FD6E0D8C06451F9 /* ErrorUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86FC0E79C1FE92FB2234ADB0BE668E87 /* ErrorUtility.swift */; }; - B5D27A8F63B37DE88C0F521218B7F66D /* NSImage+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CF292D056F5D302553FC320659C05291 /* NSImage+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B7C477EDDDC724E7EBAE9893E4467713 /* Curry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B4F914D5FC0B1958CA70FE28F125D23A /* Curry-dummy.m */; }; - B7F38094C20E5202546D12EF5DC5BA64 /* QuickSelectedTestSuiteBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5271EC894F3143DFB2B40E1F8339F726 /* QuickSelectedTestSuiteBuilder.swift */; }; - B871DFB0E5946358638D39DEF7C0BBBE /* NSObject+ObjCRuntime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542C83EC4E362B1E4036EDB131C4B2CE /* NSObject+ObjCRuntime.swift */; }; - B9BD565DAB07F8E2288A960A1D3EFAC1 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 271B749B3794F95755E02521F7C6895C /* MatcherFunc.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - B9F9DF2277C1031310BE0F0A4523453E /* RLMAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = A901B8CEB82AF015D61F999D5A7E8D71 /* RLMAccessor.h */; }; - BAAE8C77EE92C1E16375D215401708DD /* Result-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6400A354816834BB21D4290FA9222D2B /* Result-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BB10A2D0B1EE5B1BA811354116F83E3F /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5876B32CC2BEF0944820D2E3E548C6 /* CwlDarwinDefinitions.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - BB13C29F36F88E24711C0D790C3CFF92 /* RLMObjectStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1650DFF9CACF5854F584E793258BA15C /* RLMObjectStore.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - BB481B9492DBF78300596180623575D8 /* RLMListBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A6D3216BE419DC5864B02E6F2201C034 /* RLMListBase.h */; }; - BB81CE2D910A8A5099C430B1C6F5BC7D /* Quick-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 73AE9B430B7AAACCF9A62DA30EA4131D /* Quick-dummy.m */; }; - BC9025FC6C536CA7CF2287A6B5FA2DE4 /* RLMClassInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = F29326791202F9E0471DC360A0117CBF /* RLMClassInfo.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - BCBC5102BF00569BE8309116B3B8BBAD /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7BEE7345BAAC8C6F0C4171128F4B21 /* Result.framework */; }; - BD360A232FD63096C5CDB1735052FE17 /* Marshal-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EF7846F5E3452A9E25F6256E9C1ADB8 /* Marshal-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BD5D50C5CFE4027E783E36FC4D299AC7 /* RLMSyncUtil_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 0ADA20B5CF9E864675679D4999BF006D /* RLMSyncUtil_Private.h */; }; - BD7F27110A8B2F68ACBDD25490520BE7 /* ReactiveSwift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 149397BEB7B8CD201897499DD648374E /* ReactiveSwift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BD8449C1DB198C15FACCCA745AF36D92 /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 678DB41814A5FDAC91F12190877D99F4 /* NSData+ImageContentType.m */; }; - BDDE3C6B36C7A4390AFF01C125D87A27 /* Argo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CBCD6FCBEC9D5717693AB91F54AC96 /* Argo.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - BED3F012B1EDED44A23FBF2A3CA23CB1 /* RLMSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0196CF826E8303E0BAB94B7B6EA71FDB /* RLMSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - BEF2B54AC7818694E122DA3548B79681 /* RLMObjectSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C4A7A857A352C067C32F07E9DED5F857 /* RLMObjectSchema_Private.h */; }; - BEF9C3C58FEBBAAFC6640C532864F568 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1825C4323B1B212C8024BCD288E82126 /* Action.swift */; }; - BF3AF1D2B46E09E2B3DCC824E6C1F5AF /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44635410948DB4459D0131ECF77E61BA /* Equal.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - C09D570B3A79DA617D07C9B6D2323F57 /* sync_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A01AEAB1941A302C8B6218CE188443B0 /* sync_session.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - C0CDAF5BAF254A851596E52FAF38E8B2 /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E01544D39F7477EE1534CC9385D68AC6 /* handover.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - C20BE5FF4A0626CCDB4A73DC55ACDD66 /* Runes-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0413DB276E107A7B52FCB083585DFEAC /* Runes-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C232796CFD79FCCDAABF9B35E90C545B /* Argo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 776B847D8D6EBDA487170EA134742F04 /* Argo.framework */; }; - C25ADF86A646FC616F96E8CA06192B19 /* list_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB85B3D7A8C497D83BA5909F75169A46 /* list_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - C327C9F490380C6019459D5EF07D1B6C /* RLMArray.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 67DB0CBF7F97920F9ABEFC7BC7BE9DA3 /* RLMArray.h */; }; - C3F0F4913987F8646FB5D8B98AAC537A /* RLMMigration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = B9C086F9429415130B95A4D9BD539C4A /* RLMMigration_Private.h */; }; - C4D08B9404BD329475A50375AAE605C2 /* RLMSyncPermissionChange.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = F27228CB12B965FDC0DD1256B8843676 /* RLMSyncPermissionChange.h */; }; - C4FC16D9DD995BBF6F7B0E5F3DD31FCB /* Pods-ACKReactiveExtensions_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E38F0DF683B927E30C0D6581557086D /* Pods-ACKReactiveExtensions_Example-dummy.m */; }; - C5DFC8128DE5000694C911873D37B444 /* Runes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EDC7231C6D843E39DC3BD8D5B07DCEA /* Runes.framework */; }; - C6037A0DB77BF50C4C4C2BA7927DCDDA /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F93A29DAA06C2D060AB252DB6933C6 /* UIImage+GIF.m */; }; - C6825DA2061A1ABE3E81472FC8B71D69 /* NSData+ImageContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5307203EC65D843D6218225D81406D62 /* NSData+ImageContentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C7A1B68E995EA94EA9E43F0567571260 /* Argo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C95B66D60B294D43AF10B595F8B854CD /* Argo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C84CF51F332CDEC87E64A81BE83DA663 /* RealmSwift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = FBEAFC9508E42802E0BBA63D0F16AC56 /* RealmSwift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C9C828040F3DBE5B0A5025B14E707C00 /* decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E8CB9721CAD2839C372D9DBF7DAF3F /* decode.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - CB33C7EB63C52EA65AB2E0E783BD0F4C /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A6F6A940D43A1D2FB5248808880F468 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CB7558CCDD935C9E82BBF454022ED1D3 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D83EDBD81AAA3246E77DEF3354B760 /* Expectation.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - CBCA79D60C523A0239828C53E17BB892 /* NSString+QCKSelectorName.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A77A4C2A72C73B57B3099B36D9B02BA /* NSString+QCKSelectorName.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CCA07256E95D4549E1B676A49DE9FD31 /* RLMResults_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = E48EF4343180C760186C4E41CAD7F000 /* RLMResults_Private.h */; }; - CCF1BE4015BB558C6B1687F3B0CBA0F1 /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E2150184B2621EB4006941B2B9094AB1 /* shared_realm.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - CE1C31CE57468C2E05474E1FFF3935A4 /* UIButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C64BBAFB45039E89DFE105FF7DD48E4 /* UIButton+WebCache.m */; }; - CE1D57D33061B0827F195EFE28B52397 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - CE32FEAE90ECCBB0D45FD9C86F3F497A /* ReactiveSwift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B2FE7CF151309D9D3878192E09F3A3FF /* ReactiveSwift-dummy.m */; }; - CE3FA6AE0944D4AE737F0E57CFF4A615 /* HaveCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FFEB587006CF17159C316E5FEEF46D5 /* HaveCount.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - CE4CEF6328E255B380E2B2692B351CF8 /* MatchError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C206A1AEEA9ABF086EFA4DB5A915A02 /* MatchError.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - CEF75293C8F07B399E5A5F46968AC436 /* RLMRealm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 37F3E162DF05333F41599C41E7EA11AC /* RLMRealm.h */; }; - CFE009BB73AE7293B985BC0CDF383C17 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD5EBA74745951058FAC1CA3A947A45 /* UIView.swift */; }; - D01D557A69E81674354B47FEBD5367F2 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ADBD21F01F274E89DC35F39684A72FD /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D022C285A2A086CB21E6B0049754FFDE /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79AD58BD3EBDD205E05F8B3706FBB64D /* ImageIO.framework */; }; - D06E63966143D6B1035F5BCC4DE097D0 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = 55EF9D5B346E69E9CFF60DDC13761112 /* UIImage+GIF.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D123B004D9CE2F73F9634ED353BF73D1 /* UIActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECEA795175788999B204BC44FBD48FE0 /* UIActivityIndicatorView.swift */; }; - D1B581D92B0A4F072D507107AE29A868 /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59733EB1ABE53D9A3DFD27170F416260 /* index_set.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D255839B59A184FDC60BFA1ED5F77D70 /* RLMProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A1F6288289D29790139F1B3F4860185 /* RLMProperty.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D32FDDC568FBE1D35CC4874A89119842 /* Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E0C2146E06F8FE932AAC749F843932D /* Migration.swift */; }; - D3DF9582A32ACA322C7E53CF9F84F6AD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - D4AAF2FE4030CF1DD1BA5F9F80F5A1E1 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 5573F218EC3FDDACDF98B941DAB1A9CE /* SDWebImageDownloader.m */; }; - D4D99061282E453A52733AF044F457D5 /* RLMOptionalBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 60A002572AC20E5406A90AAC57DFF042 /* RLMOptionalBase.h */; }; - D57D490D0D836258B35BA8A23485D2A9 /* UICollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F52136FC50F5C79B01F64DDC695D94 /* UICollectionView.swift */; }; - D592A43EA0A6661FEDFC543CD918BE4D /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7905E8E9D37C85C9BD0EB303513B3E0 /* SignalProducer.swift */; }; - D5CE2FB299B0649CDE47146A0FC50CEB /* ObjC+Selector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4315946D5C791A0D917C598507FA8253 /* ObjC+Selector.swift */; }; - D602384EAB9294B10FC4654275B2B2F8 /* RLMSyncManager_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 60E31CE3FBB85A560035ACF301565420 /* RLMSyncManager_Private.h */; }; - D6043A4050187335511987CA83C576BD /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD4D3B5508FC4EA5098E468A3E41EA5 /* SuiteHooks.swift */; }; - D60B6F772463491CCCF5F44561DB986B /* RLMSyncManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E756BFADC9AAFF0AE85096AE9A526B5 /* RLMSyncManager.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D71BFF2B8F256E8338E928C7D8C5D772 /* RLMSyncUser.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = B4DB6173F603EAE2C38283B1018FE1AD /* RLMSyncUser.h */; }; - D72577F4B267DDCD354BE852C172A986 /* RLMObjectSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 839C4A8D444DC868D4C610DE4723D033 /* RLMObjectSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D7B86895FEFA5E23D5727970A1ECBBEE /* RLMObservation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 64BA96A52A8B3B259F42459013F60BE8 /* RLMObservation.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D7C51ACAD71B7C2F4474038108BAE033 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = AE079783607F84C877F15ED9EB6260EF /* UIImage+MultiFormat.m */; }; - D7F7FC24D36B21EF375AAFD627570108 /* RLMRealmUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 469F6A5444E5788B3E182DD479E78253 /* RLMRealmUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - D88575ED37BC462E8130CDBEFE9EA308 /* XCTestObservationCenter+Register.m in Sources */ = {isa = PBXBuildFile; fileRef = A00AAA4C6E10464A3405F98A180C3FB0 /* XCTestObservationCenter+Register.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - D8B652781696C5589246426D45B4927F /* Monad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AAA847DA79BD612A271055247BD13EE /* Monad.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - D986A3D28BC280B3A90CA9F06762338D /* UISlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E568962EBFCCAF4358F8957D8821A82C /* UISlider.swift */; }; - D9AFC3FCAC0A5683669C9096964D307F /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE8A03AFB4C021181EED12B188D46578 /* RealmSwift.framework */; }; - DAC615B84E1D443E451B2A98E9801950 /* UIView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1B02C1EEE359F771F58A0FEE948908 /* UIView+WebCache.m */; }; - DC32331BE565888E694E1321BB1D80F5 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CF93C5412F9C4395C0E134F672EE31 /* NMBExceptionCapture.m */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - DC420EAA63E76A8DC77AB16713784AAF /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB9CD136253747ACFF7E6ECE6200A47 /* Optional.swift */; }; - DCEE854E62441E78FED15CC994497F61 /* AllPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DABADFC45B8EE874A1A92B9AF644D9A /* AllPass.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - DE68DF962964EF8F48B3008054DBA6F4 /* SDImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 89BE574C4E94967835529C99140316AE /* SDImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DFEA6137784B39F884FF87F2E6B7BC9D /* MKMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38CF7AFDBE6488050A4824C4E23C0777 /* MKMapView.swift */; }; - E3500BC64541901292BF37F9FDF7F503 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21E816A500F1336215A73436B16258F1 /* Deprecations+Removals.swift */; }; - E35405BCC79C15E4591DE81047BAFD54 /* RealmCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6471A97D6C579D396EA6FC04E28003A /* RealmCollection.swift */; }; - E3A69E75DD947FDCF2FFD3E6832DE80D /* UITextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4F88E0FF65CF094BD268C7C6D05A892 /* UITextView.swift */; }; - E42A8DC24A5489DFCE54941E1EAFF183 /* Quick-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2657D40333ACDCFA69A0753858C1099E /* Quick-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E559A2BC2DEE2CD8A1AFD646921456C7 /* RLMProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 7933A983C1B0B4BC46FB1FC2C3BDDD66 /* RLMProperty.h */; }; - E5CB937578428DF7549E98D85827A430 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC5C6C2D5404C2EA7B3C1FE285AD756 /* Realm.framework */; }; - E5CCEF0B83F8272D10671C01AAE4FFA0 /* NimbleXCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ADA808F7F6AD97110E89F0B217B8654 /* NimbleXCTestHandler.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - E74D73C43866201F2DD30F5FCB640A1C /* FailureCoalescing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B048703246CB0B6033583241F45580B /* FailureCoalescing.swift */; settings = {COMPILER_FLAGS = "-whole-module-optimization"; }; }; - E834B61262C2E6907A070CE144025B96 /* keychain_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A33FB7ED3C98C702DBA6A53A8A1D633 /* keychain_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - E88C2850063783DB767F109BD95AC310 /* ObjCRuntimeAliases.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DD8D6C38CF84B39C4CD925866FE29A2 /* ObjCRuntimeAliases.h */; settings = {ATTRIBUTES = (Private, ); }; }; - E922F348FD0F1B83ABCB3F2E504FE9DA /* Marshaling.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9720D39B736427B7A488A19D48B7481 /* Marshaling.swift */; }; - E941A5BA1BB185722A1EC12563319957 /* SDWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EBF692D6358518BFD66A3A1AF49F829A /* SDWebImageManager.m */; }; - E986F95A33256E7B344FCB5209E6E0D7 /* RLMOptionalBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 60A002572AC20E5406A90AAC57DFF042 /* RLMOptionalBase.h */; }; - E992CC54CAA1360B9C2E528F9AB2BBAB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - EB220DD776AE8EACA1486B5F8622E7C6 /* Runes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EDC7231C6D843E39DC3BD8D5B07DCEA /* Runes.framework */; }; - EBA52C16F42E42A1824D87C284F4A60C /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF327CD37DCDC6B4C4D9F34962D9CEC5 /* PostNotification.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - EC385AF793862383430508BE0072131F /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D8C1F9916E66215E027888318CD599 /* List.swift */; }; - ED11AA80B871081BE92E7F0B6227C947 /* Flatten.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660B1F6A04701B2F3FF99A48AAD00CDC /* Flatten.swift */; }; - EE8E7C82DF6B54515AAFE7485EF4F011 /* RLMObjectBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = AA9436789E37E80359F8A2176F388D3B /* RLMObjectBase.h */; }; - EF31FCE477E3637A878F6AA985BEBEFF /* RLMSyncManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 60E31CE3FBB85A560035ACF301565420 /* RLMSyncManager_Private.h */; }; - F0B3BF5F2834AF5BFB44A2466DBEC6B5 /* SDWebImageDownloaderOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 585421F892EECE0D46E02A75FADF3D32 /* SDWebImageDownloaderOperation.m */; }; - F2A57ADA158E56674CF2B6D0282A88BD /* placeholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5953293A5C09A44DF3E762819A0D6161 /* placeholder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - F3B615FFC3A13BF34DC81A0317BEBE31 /* RealmConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19BA2C6CAAD1B833C0CA3E10317055BD /* RealmConfiguration.swift */; }; - F427D567DA533EBDCFA8B56EFF610FB1 /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7680BAC933258EEFB43803FE7F3B4BA9 /* ExampleHooks.swift */; }; - F428C76822F51B95430152540237DCDC /* RLMObjectSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 85FB91F281737568C40E1BE91EC624BE /* RLMObjectSchema.h */; }; - F48D38DD2EBA98D8EBFCF74AA0DD1CEC /* WebKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68CFF6EA076886323E883D239FC2D72F /* WebKitExtensions.swift */; }; - F4A1B7A059AAA6727EB70E58E09332A4 /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0164F42CC6FE0DCACF764700A6AA70EE /* CwlCatchException.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - F52F5D7F862F1BA244BCE80CDAD92C38 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CE2BD9967BB2A97F75D2501EA5D3A2 /* Core.swift */; }; - F5464A5C3C64326209B55E4B23FA6B46 /* RLMRealm_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B4B4D235F8BAAE064E0DFCC37393113 /* RLMRealm_Dynamic.h */; }; - F60D221B548716DF35193FC2CF244676 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F298A6855749549EF58B48DBA763B3F /* BeAKindOf.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - F61FCAACA8730FF6AECC66A0E983D5AB /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 500126F1D939EB7923C0A0A4FE4E7119 /* Observer.swift */; }; - F693D0A9E0D05F815A85DC258E75AF8D /* CurrentTestCaseTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E943780D14D82033A5A724B6B18E47 /* CurrentTestCaseTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; - F76AECB4FEE9BF37ED8996A9D12C3245 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A1A26B81673A0FA39FB285C2142D4A8 /* Event.swift */; }; - F7F22DF927703C41524BF33CF14A45CF /* Marshal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B029BDAAC30411CD158C72947848BD8 /* Marshal.framework */; }; - F86CA9F23356AF5E227F45E3D6903216 /* RLMCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 09EBF73F678AC49042C057CECA6D9C9B /* RLMCollection.h */; }; - F8F0A3F931CCF20B92657930620C717E /* World+DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 30310BC4025C165E16B519BF5CD34CE9 /* World+DSL.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F9D61EB5EEB799105913685722FF4C9C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B2E01CA5514B90525ECF3E081451287 /* NimbleEnvironment.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - F9E05A63D447B51E008B89731192FE7F /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E69C8B15E7E7EC1D9A652DAC2784B0BB /* AssertionRecorder.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - FA0A6F9E0A66709A35DD40296E9C5BF8 /* NSObject+Intercepting.swift in Sources */ = {isa = PBXBuildFile; fileRef = B677F06DEB90ACF09C4C2C2E387E24A1 /* NSObject+Intercepting.swift */; }; - FA3BDC52A3FA323A4ABA7A088AB017C5 /* RLMAnalytics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E8CE214B1B86DA92092AE2CAA9E7725 /* RLMAnalytics.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - FAB4ECE0C5039D99BB7173880670871D /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F1EE46FE6D88D9792F383AF2EE5E79 /* BeLessThanOrEqual.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - FB04F3F241FDB88DBBBAE98321C664C4 /* UISearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9441F22F2A6487F20303AD5F44F9AD34 /* UISearchBar.swift */; }; - FBAD342C95EDAC2AD5EDA2486B61D8D1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */; }; - FCFFEB587281358CFF05A65ED9E94C12 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D657F808F31DBEC7DF6D04AE5FF7C0 /* Functional.swift */; settings = {COMPILER_FLAGS = "-DPRODUCT_NAME=Nimble/Nimble"; }; }; - FDC5E9CA22F2BB8936B753A35A1F56A5 /* sync_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE26BE6B3B2A24098629C1CDA4775E7C /* sync_user.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - FE0960CB3A0995754417914479949CAA /* RLMSyncConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C2123A0484B67CA9CC476814C0120E75 /* RLMSyncConfiguration_Private.h */; }; - FE4AF0E2D0E1E345B5F3C22F3AE323D6 /* collection_notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEA8A273E8F0B9F8F7DF5BE1EF5F429E /* collection_notifications.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.2\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC"; }; }; - FE9D756C4D34F0A837D5B62670C54BBE /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511961DB43E641DA6E916E03D4AD14F4 /* Schema.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 022F2C53878C86B427D49C3F9A3F3B42 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F01F6ACDF071C28A104A302C201DFFD2; - remoteInfo = ReactiveSwift; - }; - 02A5AB4173D4402D58F8C21847227712 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F01F6ACDF071C28A104A302C201DFFD2; - remoteInfo = ReactiveSwift; - }; - 0A564D03D6479A675AFBE689013DC63C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8107DB93200934B6DEFD700F43910AC7; - remoteInfo = Result; - }; - 1167D2DE6A16514175322EE736D83EE8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = B3817DFA9BAAAB53C9A56A08FE0387CA; - remoteInfo = Realm; - }; - 2564FDF9181BB0A672BDFA61DCA33F56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = DE3EBDE84D7632BA2C58988A7A5C141B; - remoteInfo = ACKReactiveExtensions; - }; - 268F06059105B11F6A19C7F0679FC51A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = B3817DFA9BAAAB53C9A56A08FE0387CA; - remoteInfo = Realm; - }; - 2C898CE5E8147B2BD048279BE6C7317B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = B3817DFA9BAAAB53C9A56A08FE0387CA; - remoteInfo = Realm; - }; - 33E82E5C3635B42630BFFA63C9EC6C0B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E29F3F45BD6B823A2EC56ECA2397070; - remoteInfo = ReactiveCocoa; - }; - 394E0F163CF3B2834941FC5B067331DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8107DB93200934B6DEFD700F43910AC7; - remoteInfo = Result; - }; - 417783C84CE41C58CD2E25AEF053BCCD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 540B755C72E99D2B6A76D13262796807; - remoteInfo = SDWebImage; - }; - 4A80235A77DA5B5B48FCBEF03BF7DEFC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = D6A1B9EB7A50D88E5565BEFC1946E68B; - remoteInfo = Marshal; - }; - 5A4C7A8D7284158723FD02FD72F00B39 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E29F3F45BD6B823A2EC56ECA2397070; - remoteInfo = ReactiveCocoa; - }; - 5BD206E940F70B7E7AE6A909BC2C61F8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 96D93470C408341136D1AE696D2459E6; - remoteInfo = Quick; - }; - 6184E1225CF5815F75CA581A380FFD51 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E4CE6EDCFC306EAF6969FB5567CF4AD; - remoteInfo = Runes; - }; - 6210B71103B7F90F828D2B87B34142F1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = D6A1B9EB7A50D88E5565BEFC1946E68B; - remoteInfo = Marshal; - }; - 62DA32FF9205D947E5D37231C7726BAB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3DE0C97A2313CC9DA982FBC2C12E6B42; - remoteInfo = Argo; - }; - 6CDCE1EEACE7899769F18927F4111DE9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3E12B2B47078F77F5CB8A10C0EF8C1AF; - remoteInfo = Reachability; - }; - 6EBCE95BB06D9C588FAD46C8EBA294C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E4CE6EDCFC306EAF6969FB5567CF4AD; - remoteInfo = Runes; - }; - 71F48D6AFD4DCEE19FD35D4D39F85499 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = B3817DFA9BAAAB53C9A56A08FE0387CA; - remoteInfo = Realm; - }; - 8091F6A1327D78C8C10D62251E2510DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 540B755C72E99D2B6A76D13262796807; - remoteInfo = SDWebImage; - }; - 8551F1078176927D36C6EDDF4596B1E8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3E12B2B47078F77F5CB8A10C0EF8C1AF; - remoteInfo = Reachability; - }; - 868623CB91EED714AE22B5BE7019EF20 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = DE3EBDE84D7632BA2C58988A7A5C141B; - remoteInfo = ACKReactiveExtensions; - }; - 939ECA5E7E12D9730CCDDF264267E9B4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 540B755C72E99D2B6A76D13262796807; - remoteInfo = SDWebImage; - }; - 98CB46E129F42EF1B9E86F530C41C0C1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F01F6ACDF071C28A104A302C201DFFD2; - remoteInfo = ReactiveSwift; - }; - A163D67065A494CC460A62DDA52ECAA9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3DE0C97A2313CC9DA982FBC2C12E6B42; - remoteInfo = Argo; - }; - A9EB70C31D66DCC3ED09E412F72CD09F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8107DB93200934B6DEFD700F43910AC7; - remoteInfo = Result; - }; - AFD595F6FDE15902D45F069F4C458AC6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E4CE6EDCFC306EAF6969FB5567CF4AD; - remoteInfo = Runes; - }; - B1C9F8CA435D6E088C485E8726B78F07 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F01F6ACDF071C28A104A302C201DFFD2; - remoteInfo = ReactiveSwift; - }; - B35FE5201D658D1C8DA0FDFEA34456A0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8107DB93200934B6DEFD700F43910AC7; - remoteInfo = Result; - }; - B4DCEAB745F20AE0FB56B3DB6A35235E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8C3D90B09D20CB4C804DD2F29D525C27; - remoteInfo = RealmSwift; - }; - C1C6665408CE50FC216823264320A845 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1321E318D10CFDC9F5B93A7952492CCD; - remoteInfo = Nimble; - }; - C36D1D094529C4D7F4339B028399C99C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = D6A1B9EB7A50D88E5565BEFC1946E68B; - remoteInfo = Marshal; - }; - C557DDCD838ACA25676D02354BE3C7B2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3E12B2B47078F77F5CB8A10C0EF8C1AF; - remoteInfo = Reachability; - }; - C65F8FECD9E4F74DB9E21B1C56C2A140 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E29F3F45BD6B823A2EC56ECA2397070; - remoteInfo = ReactiveCocoa; - }; - DCC7FC76106F1AEC1288E08AA2B978DB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8C3D90B09D20CB4C804DD2F29D525C27; - remoteInfo = RealmSwift; - }; - E55B8EBE25B8676FE9343EBD6AD358D1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8107DB93200934B6DEFD700F43910AC7; - remoteInfo = Result; - }; - EAA9CB03B2D6C959FB38608F9FABC3AB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 8C3D90B09D20CB4C804DD2F29D525C27; - remoteInfo = RealmSwift; - }; - F95C7236AE93166C9F763DF2C9A2738F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E4CE6EDCFC306EAF6969FB5567CF4AD; - remoteInfo = Runes; - }; - FDD249EAA8F66FD9AE57489AADD87277 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3DE0C97A2313CC9DA982FBC2C12E6B42; - remoteInfo = Argo; - }; - FFB5EEA82BFF4012ED49686CC1679DF2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 378E1575B1A77DB0CC90AD1E5B4E59B9; - remoteInfo = Curry; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - CD4364B2F240FB4B7758A102B4805960 /* Copy . Private Headers */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "$(PRIVATE_HEADERS_FOLDER_PATH)/."; - dstSubfolderSpec = 16; - files = ( - 4D98988A627FC32461D79A732C4349BC /* RLMAccessor.h in Copy . Private Headers */, - 4C7DBD5B1AB61B1BEDBEB1323EBE7317 /* RLMArray_Private.h in Copy . Private Headers */, - 52F86970C84888E35702F50A03E6BC74 /* RLMListBase.h in Copy . Private Headers */, - C3F0F4913987F8646FB5D8B98AAC537A /* RLMMigration_Private.h in Copy . Private Headers */, - B195B58E4827B58E91267521354F3F19 /* RLMObject_Private.h in Copy . Private Headers */, - BEF2B54AC7818694E122DA3548B79681 /* RLMObjectSchema_Private.h in Copy . Private Headers */, - 3F156158393F8DC42F95948E071B69E6 /* RLMObjectStore.h in Copy . Private Headers */, - E986F95A33256E7B344FCB5209E6E0D7 /* RLMOptionalBase.h in Copy . Private Headers */, - A9645EB788CD6208F3B7621866869B16 /* RLMProperty_Private.h in Copy . Private Headers */, - 9FFE05121CBF14144F5F16B8F98B120E /* RLMRealm_Private.h in Copy . Private Headers */, - 4832ADCFB52202045E43A4BF8FF60678 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */, - 855E10DB10F413F8CF85BDBF88648566 /* RLMResults_Private.h in Copy . Private Headers */, - 0D3E0358F622711CD56F3694492773A2 /* RLMSchema_Private.h in Copy . Private Headers */, - 62426F69BA1918E570C08AED191EF40F /* RLMSyncConfiguration_Private.h in Copy . Private Headers */, - D602384EAB9294B10FC4654275B2B2F8 /* RLMSyncManager_Private.h in Copy . Private Headers */, - 4C2E161BCF00CED28660CE7130DE6A83 /* RLMSyncPermissionChange_Private.h in Copy . Private Headers */, - BD5D50C5CFE4027E783E36FC4D299AC7 /* RLMSyncUtil_Private.h in Copy . Private Headers */, - ); - name = "Copy . Private Headers"; - runOnlyForDeploymentPostprocessing = 0; - }; - F4BEC5AA00AE5B9B9FD5EAB69A468543 /* Copy . Public Headers */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/."; - dstSubfolderSpec = 16; - files = ( - 09402F4421E1C056D442CB795B8720F7 /* Realm.h in Copy . Public Headers */, - C327C9F490380C6019459D5EF07D1B6C /* RLMArray.h in Copy . Public Headers */, - 0CA86759153D45C3EBF8C648919EB6D0 /* RLMCollection.h in Copy . Public Headers */, - B17717D3BA6E567367D929686CAA194C /* RLMConstants.h in Copy . Public Headers */, - 2705B708FF1C570FF972261A787F4D8A /* RLMListBase.h in Copy . Public Headers */, - 88A62885EEF84639E1377060A8CCAFCD /* RLMMigration.h in Copy . Public Headers */, - 945EFCE55FCC4F5717B597E2B23340E6 /* RLMObject.h in Copy . Public Headers */, - EE8E7C82DF6B54515AAFE7485EF4F011 /* RLMObjectBase.h in Copy . Public Headers */, - 7A4CD8BE858355870E06DB4D9EC4C5A4 /* RLMObjectBase_Dynamic.h in Copy . Public Headers */, - F428C76822F51B95430152540237DCDC /* RLMObjectSchema.h in Copy . Public Headers */, - D4D99061282E453A52733AF044F457D5 /* RLMOptionalBase.h in Copy . Public Headers */, - AE5A2C5AD3EE2306BCDD6000AE71B929 /* RLMPlatform.h in Copy . Public Headers */, - 39361705F2A05FB0C6860DB744A9481A /* RLMProperty.h in Copy . Public Headers */, - CEF75293C8F07B399E5A5F46968AC436 /* RLMRealm.h in Copy . Public Headers */, - A428E7476E5AC5EFEA2407865C6BE9D9 /* RLMRealm_Dynamic.h in Copy . Public Headers */, - 2C26E0D45E4B6A28AFA45D3EAC8ADA90 /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */, - 166B53AE7422AE81185DE33BA4B1DADF /* RLMRealmConfiguration.h in Copy . Public Headers */, - 940ECA327E68E6CBA664C18A2C621317 /* RLMResults.h in Copy . Public Headers */, - 78D42446501980211659468501F92508 /* RLMSchema.h in Copy . Public Headers */, - 1F3FDD37763AE6B26320B1E99269233F /* RLMSyncConfiguration.h in Copy . Public Headers */, - 5F138050A5C0C08631AE1C299A6E9057 /* RLMSyncCredentials.h in Copy . Public Headers */, - 1A0790CA03A6E9E3D8377F2FBB69BD4B /* RLMSyncManager.h in Copy . Public Headers */, - C4D08B9404BD329475A50375AAE605C2 /* RLMSyncPermissionChange.h in Copy . Public Headers */, - A9FAD00B27400DC8EC15C440F098B5C0 /* RLMSyncSession.h in Copy . Public Headers */, - D71BFF2B8F256E8338E928C7D8C5D772 /* RLMSyncUser.h in Copy . Public Headers */, - ADBC05DA5968674948A96809175229FF /* RLMSyncUtil.h in Copy . Public Headers */, - ); - name = "Copy . Public Headers"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0022F7705FB317525EB64D8310D6EA4E /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCacheOperation.m"; path = "SDWebImage/UIView+WebCacheOperation.m"; sourceTree = ""; }; - 01060E818490024E600D55519EB092E1 /* Realm.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Realm.swift; path = RealmSwift/Realm.swift; sourceTree = ""; }; - 0164F42CC6FE0DCACF764700A6AA70EE /* CwlCatchException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlCatchException.swift; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift; sourceTree = ""; }; - 0196CF826E8303E0BAB94B7B6EA71FDB /* RLMSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSchema.mm; path = Realm/RLMSchema.mm; sourceTree = ""; }; - 01D68A2A4CAE81125EC2676085493945 /* RLMSyncUser.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncUser.mm; path = Realm/RLMSyncUser.mm; sourceTree = ""; }; - 02C78CD73F93EA8B253C2061F339748D /* Quick.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Quick.xcconfig; sourceTree = ""; }; - 02C9F75B74BA0614F8A1E06E422F7303 /* RLMListBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMListBase.mm; path = Realm/RLMListBase.mm; sourceTree = ""; }; - 037388FFAA7D6DD4BCFB36762737DC94 /* Stringers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Stringers.swift; path = Sources/Nimble/Utils/Stringers.swift; sourceTree = ""; }; - 03AB32EFA3403D705D88D68795CBFACA /* Scheduler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Scheduler.swift; path = Sources/Scheduler.swift; sourceTree = ""; }; - 03B463B62FF6326026FA653E42C9926D /* DecodeOperators.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DecodeOperators.swift; path = Sources/Argo/Operators/DecodeOperators.swift; sourceTree = ""; }; - 03C9AF42C06446ECC6AAFF6D6802866D /* thread_confined.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = thread_confined.cpp; path = Realm/ObjectStore/src/thread_confined.cpp; sourceTree = ""; }; - 03DA588FB6070395B43FDADC81595098 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Result.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 03F8C403E25985E9B3F49A7D80B55B8F /* EventLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EventLogger.swift; path = Sources/EventLogger.swift; sourceTree = ""; }; - 0412A85F1E6549BEDB139D20B1ED081B /* UIBarButtonItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIBarButtonItem.swift; path = ReactiveCocoa/UIKit/UIBarButtonItem.swift; sourceTree = ""; }; - 0413DB276E107A7B52FCB083585DFEAC /* Runes-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Runes-umbrella.h"; sourceTree = ""; }; - 04FFAB12851B9DEC440905468EFB3DF8 /* ObjC+Messages.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ObjC+Messages.swift"; path = "ReactiveCocoa/ObjC+Messages.swift"; sourceTree = ""; }; - 05310AA14FB2E89FACDD353E85A90C83 /* Nimble.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Nimble.h; path = Sources/Nimble/Nimble.h; sourceTree = ""; }; - 059A2B4445E82FAF328D7F61095B3AFB /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = weak_realm_notifier.cpp; path = Realm/ObjectStore/src/impl/weak_realm_notifier.cpp; sourceTree = ""; }; - 05D6C2456AFE9C400319370C741B2E60 /* World+DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "World+DSL.swift"; path = "Sources/Quick/DSL/World+DSL.swift"; sourceTree = ""; }; - 06D29CE181107BC1B82D7636DB86EA74 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.markdown"; sourceTree = ""; }; - 07B1B4AF823C9F4BA40CFD18D903C114 /* Curry.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Curry.swift; path = Source/Curry.swift; sourceTree = ""; }; - 0894A8ECFDE6892A88F6E589924D3B30 /* RLMArrayLinkView.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMArrayLinkView.mm; path = Realm/RLMArrayLinkView.mm; sourceTree = ""; }; - 09D5E0D36BF6CBA6279636E425EA8DD3 /* UIStepper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIStepper.swift; path = ReactiveCocoa/UIKit/iOS/UIStepper.swift; sourceTree = ""; }; - 09EBF73F678AC49042C057CECA6D9C9B /* RLMCollection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMCollection.h; path = include/RLMCollection.h; sourceTree = ""; }; - 09F87A26DBCDFFF48E7D97BF667F86B1 /* Dictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Dictionary.swift; path = Sources/Argo/Extensions/Dictionary.swift; sourceTree = ""; }; - 0A006DAB665D087A81363738F07BB8F8 /* RLMAccessor.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMAccessor.mm; path = Realm/RLMAccessor.mm; sourceTree = ""; }; - 0ADA20B5CF9E864675679D4999BF006D /* RLMSyncUtil_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil_Private.h; path = include/RLMSyncUtil_Private.h; sourceTree = ""; }; - 0ADA808F7F6AD97110E89F0B217B8654 /* NimbleXCTestHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NimbleXCTestHandler.swift; path = Sources/Nimble/Adapters/NimbleXCTestHandler.swift; sourceTree = ""; }; - 0B4E3DDA1CC29A78E565F115A8A00DD8 /* Reachability-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Reachability-prefix.pch"; sourceTree = ""; }; - 0B548C79D533C48D007E1AC4D8658EC9 /* catDecoded.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = catDecoded.swift; path = Sources/Argo/Functions/catDecoded.swift; sourceTree = ""; }; - 0C12F0313F515579E91389CB53B065D1 /* Runes.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Runes.xcconfig; sourceTree = ""; }; - 0C5E10D98138D539CCF68FF7A5EDDAF1 /* ReactiveCocoa.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = ReactiveCocoa.modulemap; sourceTree = ""; }; - 0D0F4809D8692C621FA463BF89809892 /* RLMResults.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMResults.mm; path = Realm/RLMResults.mm; sourceTree = ""; }; - 0DABADFC45B8EE874A1A92B9AF644D9A /* AllPass.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AllPass.swift; path = Sources/Nimble/Matchers/AllPass.swift; sourceTree = ""; }; - 0DD64BEE47F7F882E962E75DEB7F825F /* JSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSON.swift; path = Sources/JSON.swift; sourceTree = ""; }; - 0E1CDE383243D554B0D7CDF7F0A56864 /* RLMArray_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray_Private.h; path = include/RLMArray_Private.h; sourceTree = ""; }; - 0E46BEDB9FE2948BDB0C0A8EC1E43306 /* NMBExpectation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NMBExpectation.swift; path = Sources/Nimble/Adapters/NMBExpectation.swift; sourceTree = ""; }; - 0E8A2A2A21C0F8A5BE916EDDCE782ED2 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0ED9810E50E8D4C73D14E85A64344E59 /* ObjC+Runtime.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ObjC+Runtime.swift"; path = "ReactiveCocoa/ObjC+Runtime.swift"; sourceTree = ""; }; - 0EF7846F5E3452A9E25F6256E9C1ADB8 /* Marshal-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Marshal-umbrella.h"; sourceTree = ""; }; - 105FBA0BD89AFC25198AE4334E657AB6 /* NSObject+Lifetime.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+Lifetime.swift"; path = "ReactiveCocoa/NSObject+Lifetime.swift"; sourceTree = ""; }; - 107AA785555CE6CCC4A8F3E2890C4499 /* SDWebImageDecoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDecoder.h; path = SDWebImage/SDWebImageDecoder.h; sourceTree = ""; }; - 1088B70537CAD4A6E970D588E739FA4B /* ACKReactiveExtensions.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = ACKReactiveExtensions.modulemap; sourceTree = ""; }; - 10A6B890D72DD8FA3D51FA55D19A7045 /* NSBundle+CurrentTestBundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSBundle+CurrentTestBundle.swift"; path = "Sources/Quick/NSBundle+CurrentTestBundle.swift"; sourceTree = ""; }; - 12254A6FC014605B8F73CD71E05E2820 /* SDWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SDWebImage-dummy.m"; sourceTree = ""; }; - 12612EF0C0D0DB42DA16F98083C20B82 /* RealmSwift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "RealmSwift-dummy.m"; sourceTree = ""; }; - 126814190611329563A399525B529E45 /* SDWebImageCompat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageCompat.m; path = SDWebImage/SDWebImageCompat.m; sourceTree = ""; }; - 13B9E00A2ADFC7E032F45885B40B5822 /* RLMObjectBase_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase_Dynamic.h; path = include/RLMObjectBase_Dynamic.h; sourceTree = ""; }; - 142256C1FF1580722ADF79BC64D3570C /* RawRepresentable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RawRepresentable.swift; path = Sources/Argo/Extensions/RawRepresentable.swift; sourceTree = ""; }; - 144962E04851A77F7F0ADE3855B9AC12 /* ArgoDeprecations.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ArgoDeprecations.swift; sourceTree = ""; }; - 149397BEB7B8CD201897499DD648374E /* ReactiveSwift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ReactiveSwift-umbrella.h"; sourceTree = ""; }; - 15927EE2028CAB56CFB99EF18090C7CF /* World.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = World.swift; path = Sources/Quick/World.swift; sourceTree = ""; }; - 15D83EDBD81AAA3246E77DEF3354B760 /* Expectation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expectation.swift; path = Sources/Nimble/Expectation.swift; sourceTree = ""; }; - 161E419EDCBFDC6BB9FDBE5B1D181DD2 /* RealmSwift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = RealmSwift.modulemap; sourceTree = ""; }; - 1650DFF9CACF5854F584E793258BA15C /* RLMObjectStore.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectStore.mm; path = Realm/RLMObjectStore.mm; sourceTree = ""; }; - 1825C4323B1B212C8024BCD288E82126 /* Action.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Action.swift; path = Sources/Action.swift; sourceTree = ""; }; - 19BA2C6CAAD1B833C0CA3E10317055BD /* RealmConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RealmConfiguration.swift; path = RealmSwift/RealmConfiguration.swift; sourceTree = ""; }; - 19ECB52F60624E4635D8091C15D6B9E1 /* UISwitch.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UISwitch.swift; path = ReactiveCocoa/UIKit/iOS/UISwitch.swift; sourceTree = ""; }; - 1A1EDA68881B394DFBBE8D776E4FC50E /* Property.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Property.swift; path = RealmSwift/Property.swift; sourceTree = ""; }; - 1A4313403997D85BB033DC3CE9FE2DC9 /* SDImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCache.m; path = SDWebImage/SDImageCache.m; sourceTree = ""; }; - 1AA0A291C2F56AA20159C8593C7CDF27 /* UIProgressView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIProgressView.swift; path = ReactiveCocoa/UIKit/UIProgressView.swift; sourceTree = ""; }; - 1AAA847DA79BD612A271055247BD13EE /* Monad.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Monad.swift; path = Sources/Argo/Types/Decoded/Monad.swift; sourceTree = ""; }; - 1AB2EFDA17A907E630213AEDF7F8A7C1 /* RLMUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMUtil.mm; path = Realm/RLMUtil.mm; sourceTree = ""; }; - 1ADBD21F01F274E89DC35F39684A72FD /* UIImageView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+WebCache.h"; path = "SDWebImage/UIImageView+WebCache.h"; sourceTree = ""; }; - 1B3AA4360B79AA046AAE078E12F3DFFC /* UIDatePicker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIDatePicker.swift; path = ReactiveCocoa/UIKit/iOS/UIDatePicker.swift; sourceTree = ""; }; - 1BBB569FFF4629F64B98D1DE16E37BE9 /* SDWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageManager.h; path = SDWebImage/SDWebImageManager.h; sourceTree = ""; }; - 1C5ADDD6F855E81D6F9B773C776E3EDA /* Nimble.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Nimble.modulemap; sourceTree = ""; }; - 1C64BBAFB45039E89DFE105FF7DD48E4 /* UIButton+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+WebCache.m"; path = "SDWebImage/UIButton+WebCache.m"; sourceTree = ""; }; - 1DD94FC4C43F3CC593AE8596920824B9 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1DF3E05F9FFAE9E02C11FE84296F7A20 /* AssertionDispatcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertionDispatcher.swift; path = Sources/Nimble/Adapters/AssertionDispatcher.swift; sourceTree = ""; }; - 1E033FD8AF63521D07649FF36BA00D05 /* CwlCatchException.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CwlCatchException.h; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h; sourceTree = ""; }; - 1E7DA7E139F874EC8DF9C7A6D1E80337 /* NSImage+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSImage+WebCache.m"; path = "SDWebImage/NSImage+WebCache.m"; sourceTree = ""; }; - 1EF18CB021556D923160AE960C55D41F /* RLMResults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults.h; path = include/RLMResults.h; sourceTree = ""; }; - 1FC4B0E456455B6FA693C53B90618F36 /* RLMRealmConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealmConfiguration.mm; path = Realm/RLMRealmConfiguration.mm; sourceTree = ""; }; - 1FD4D3B5508FC4EA5098E468A3E41EA5 /* SuiteHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SuiteHooks.swift; path = Sources/Quick/Hooks/SuiteHooks.swift; sourceTree = ""; }; - 206E1E12150B32DB317DA4656D2D26AE /* ObjectiveCSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ObjectiveCSupport.swift; path = RealmSwift/ObjectiveCSupport.swift; sourceTree = ""; }; - 20ED7AED4F9DC9FD6F9AA9B59F0EDD83 /* XCTestSuite+QuickTestSuiteBuilder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "XCTestSuite+QuickTestSuiteBuilder.m"; path = "Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m"; sourceTree = ""; }; - 21E816A500F1336215A73436B16258F1 /* Deprecations+Removals.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Deprecations+Removals.swift"; path = "ReactiveCocoa/Deprecations+Removals.swift"; sourceTree = ""; }; - 2225060BAB6998F7631BB9AE0B59981B /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MultiFormat.h"; path = "SDWebImage/UIImage+MultiFormat.h"; sourceTree = ""; }; - 232FC4E435DA00B8472D3DBBB13915A8 /* NSObject+KeyValueObserving.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+KeyValueObserving.swift"; path = "ReactiveCocoa/NSObject+KeyValueObserving.swift"; sourceTree = ""; }; - 2657D40333ACDCFA69A0753858C1099E /* Quick-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Quick-umbrella.h"; sourceTree = ""; }; - 26BD4FA1060B2BACDEA59FBA0725A568 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ReactiveCocoa.framework; path = ReactiveCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2700DED06348763C77CC011CE6DB3AB2 /* Property.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Property.swift; path = Sources/Property.swift; sourceTree = ""; }; - 2718B96AF1AF5798736F5F61B15D2262 /* Pods-ACKReactiveExtensions_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ACKReactiveExtensions_Example.release.xcconfig"; sourceTree = ""; }; - 271B749B3794F95755E02521F7C6895C /* MatcherFunc.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherFunc.swift; path = Sources/Nimble/Matchers/MatcherFunc.swift; sourceTree = ""; }; - 285950CBD7CBC55792C73CA9492F7EA7 /* sync_file.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_file.cpp; path = Realm/ObjectStore/src/sync/impl/sync_file.cpp; sourceTree = ""; }; - 2920E42C255817A6E40496468D7DCC7D /* Realm.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Realm.xcconfig; sourceTree = ""; }; - 2925EA57D3DED1B0B8C6F5FF019EE71E /* Migration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Migration.swift; path = RealmSwift/Migration.swift; sourceTree = ""; }; - 2A05AD519EBE844EA875510DEBE70454 /* Curry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Curry.framework; path = Curry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2A1F6288289D29790139F1B3F4860185 /* RLMProperty.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMProperty.mm; path = Realm/RLMProperty.mm; sourceTree = ""; }; - 2AAD639877DAE67319D9E59A0115D29F /* ValidatingProperty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ValidatingProperty.swift; path = Sources/ValidatingProperty.swift; sourceTree = ""; }; - 2AF55CC1A2AD69D3B329C324E8B20679 /* Pods-ACKReactiveExtensions_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ACKReactiveExtensions_Example-frameworks.sh"; sourceTree = ""; }; - 2B50E6355DCACE9410E347C3F5E5FB7A /* SDWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-prefix.pch"; sourceTree = ""; }; - 2C0202A6056A7E85A9737903599CC8EA /* BeIdenticalTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeIdenticalTo.swift; path = Sources/Nimble/Matchers/BeIdenticalTo.swift; sourceTree = ""; }; - 2D3882CC443D7C99789F1CE6D7CA7975 /* UILabel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UILabel.swift; path = ReactiveCocoa/UIKit/UILabel.swift; sourceTree = ""; }; - 2D5876B32CC2BEF0944820D2E3E548C6 /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlDarwinDefinitions.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift; sourceTree = ""; }; - 2DC5C6C2D5404C2EA7B3C1FE285AD756 /* Realm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Realm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2DD872E3DA460F034CEAE40B6BC7559D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 2F3881C29F4D7B36EE3F27584F619186 /* Argo-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Argo-prefix.pch"; sourceTree = ""; }; - 2F6B92C6B8D16F1B9375EFBB3DF874C5 /* Aliases.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Aliases.swift; path = RealmSwift/Aliases.swift; sourceTree = ""; }; - 2FFEB587006CF17159C316E5FEEF46D5 /* HaveCount.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HaveCount.swift; path = Sources/Nimble/Matchers/HaveCount.swift; sourceTree = ""; }; - 30310BC4025C165E16B519BF5CD34CE9 /* World+DSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "World+DSL.h"; path = "Sources/QuickObjectiveC/DSL/World+DSL.h"; sourceTree = ""; }; - 314B8B6D64D349093EF3480BEE71626D /* Lifetime.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lifetime.swift; path = Sources/Lifetime.swift; sourceTree = ""; }; - 319D47A4E04B1D1850D15617B34731FE /* format.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = format.cpp; path = Realm/ObjectStore/src/util/format.cpp; sourceTree = ""; }; - 31EA30FAB5AC797914D7B7A65FDF520D /* RLMObjectStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectStore.h; path = include/RLMObjectStore.h; sourceTree = ""; }; - 3282A40C35AC3A6009A27E7C2E672D10 /* SDImageCacheConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDImageCacheConfig.m; path = SDWebImage/SDImageCacheConfig.m; sourceTree = ""; }; - 334F857F93FC618C80B8306EA8C02F03 /* UITextField.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UITextField.swift; path = ReactiveCocoa/UIKit/UITextField.swift; sourceTree = ""; }; - 3353ACBAA48DE70FC416B1908522FC87 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 33BC9D10BB8C5D4C51A61305E606E8E4 /* SDWebImage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SDWebImage.xcconfig; sourceTree = ""; }; - 33CB2E5C87615DE8B3C12CD9493C9868 /* Decoded.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Decoded.swift; path = Sources/Argo/Types/Decoded/Decoded.swift; sourceTree = ""; }; - 33EA03A6970E732035AFB8C2C7200168 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Result/Result.swift; sourceTree = ""; }; - 33FD8512741E03356DC3075014CB736C /* RLMSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema_Private.h; path = include/RLMSchema_Private.h; sourceTree = ""; }; - 340AC7AA1430E9A4AE03BE7D3FF434A2 /* Util.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Util.swift; path = RealmSwift/Util.swift; sourceTree = ""; }; - 3542FF4AD25D943D1E8DA607A35A7453 /* sequence.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = sequence.swift; path = Sources/Argo/Functions/sequence.swift; sourceTree = ""; }; - 35C829B3ED1CE47110FB4243A4AA1DD0 /* Reactive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Reactive.swift; path = Sources/Reactive.swift; sourceTree = ""; }; - 36CF93C5412F9C4395C0E134F672EE31 /* NMBExceptionCapture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NMBExceptionCapture.m; path = Sources/NimbleObjectiveC/NMBExceptionCapture.m; sourceTree = ""; }; - 3738F2E81E3C0A011D2B72D4A74BF811 /* RLMSyncSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncSession.h; path = include/RLMSyncSession.h; sourceTree = ""; }; - 37F3E162DF05333F41599C41E7EA11AC /* RLMRealm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm.h; path = include/RLMRealm.h; sourceTree = ""; }; - 388382BCC74E82863E7018B4C3949760 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 38CF7AFDBE6488050A4824C4E23C0777 /* MKMapView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MKMapView.swift; path = ReactiveCocoa/Shared/MKMapView.swift; sourceTree = ""; }; - 38F0C4AF028762AF6E61DC67F559B4E0 /* Argo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Argo.modulemap; sourceTree = ""; }; - 3916AC4D2E4D39199113D17AB7059BE7 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 392220F412D83DABB8377C6A3546887B /* UnmarshalingWithContext.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UnmarshalingWithContext.swift; path = Sources/UnmarshalingWithContext.swift; sourceTree = ""; }; - 39424FC5D2544CC107EC61D28A83CF56 /* BeVoid.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeVoid.swift; path = Sources/Nimble/Matchers/BeVoid.swift; sourceTree = ""; }; - 394D5A2846811D4CBC5ECA82A735FF30 /* SwiftVersion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftVersion.swift; path = RealmSwift/SwiftVersion.swift; sourceTree = ""; }; - 3A6F6A940D43A1D2FB5248808880F468 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+HighlightedWebCache.h"; path = "SDWebImage/UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; - 3A7BEE7345BAAC8C6F0C4171128F4B21 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B048703246CB0B6033583241F45580B /* FailureCoalescing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FailureCoalescing.swift; path = Sources/Argo/Types/Decoded/FailureCoalescing.swift; sourceTree = ""; }; - 3B7BD69B940C2B7FB43BDDB77643B0B7 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 3BE1B17FB3D1786D4AE6C6793272FD66 /* RLMArray.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMArray.mm; path = Realm/RLMArray.mm; sourceTree = ""; }; - 3C60070B0166160719DDB8E19B9F5462 /* RLMObject.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObject.mm; path = Realm/RLMObject.mm; sourceTree = ""; }; - 3C92847251E673E2C9A4421274F02A9C /* Reachability-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Reachability-umbrella.h"; sourceTree = ""; }; - 3CA2661FAA5D698D8172B937E805E9D0 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.debug.xcconfig"; sourceTree = ""; }; - 3D5719DF5A213B3338485A997A32CD31 /* ResultExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResultExtensions.swift; path = Sources/ResultExtensions.swift; sourceTree = ""; }; - 3E756BFADC9AAFF0AE85096AE9A526B5 /* RLMSyncManager.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncManager.mm; path = Realm/RLMSyncManager.mm; sourceTree = ""; }; - 3F8D78E35B6799FBE72ED77EF444B26F /* object_schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = object_schema.cpp; path = Realm/ObjectStore/src/object_schema.cpp; sourceTree = ""; }; - 4006BC04F14AE7E96891627AAA66B46A /* SDWebImage+RAC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SDWebImage+RAC.swift"; sourceTree = ""; }; - 404FFFD3541475853E542117FD585D0C /* Runes-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Runes-dummy.m"; sourceTree = ""; }; - 4315946D5C791A0D917C598507FA8253 /* ObjC+Selector.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ObjC+Selector.swift"; path = "ReactiveCocoa/ObjC+Selector.swift"; sourceTree = ""; }; - 44635410948DB4459D0131ECF77E61BA /* Equal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Equal.swift; path = Sources/Nimble/Matchers/Equal.swift; sourceTree = ""; }; - 45188195842AF0ADF3ECEA1309FD2F4E /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Quick.framework; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 469F6A5444E5788B3E182DD479E78253 /* RLMRealmUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealmUtil.mm; path = Realm/RLMRealmUtil.mm; sourceTree = ""; }; - 47B4D6BE656A53B5B57D0BFB9B020A68 /* Applicative.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Applicative.swift; path = Sources/Argo/Types/Decoded/Applicative.swift; sourceTree = ""; }; - 47D7EF3D5D559122CEC7B8050B62E114 /* Results.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Results.swift; path = RealmSwift/Results.swift; sourceTree = ""; }; - 48871151A824B9F49B5D29098FA2C2DB /* ReactiveSwift-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ReactiveSwift-prefix.pch"; sourceTree = ""; }; - 49D6560115C7B2BC53A70882B073C3B1 /* Marshal-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Marshal-dummy.m"; sourceTree = ""; }; - 4ABC5D71A2A908186B87517B2A07A91B /* RACReachability.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RACReachability.swift; sourceTree = ""; }; - 4AC6B8BF65E2C5C0DB2344F42211B2AE /* RLMProperty_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty_Private.h; path = include/RLMProperty_Private.h; sourceTree = ""; }; - 4DD8D6C38CF84B39C4CD925866FE29A2 /* ObjCRuntimeAliases.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ObjCRuntimeAliases.h; path = ReactiveCocoa/ObjCRuntimeAliases.h; sourceTree = ""; }; - 4E70B58DAC696F2C26DE6F3E75D22B24 /* Realm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Realm.framework; path = Realm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4F78E60DAA32E09751420F5C65B9F77D /* collection_change_builder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_change_builder.cpp; path = Realm/ObjectStore/src/impl/collection_change_builder.cpp; sourceTree = ""; }; - 4F9CE6DD770779A4EE2956B3364C4D86 /* JSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSON.swift; path = Sources/Argo/Types/JSON.swift; sourceTree = ""; }; - 500126F1D939EB7923C0A0A4FE4E7119 /* Observer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Observer.swift; path = Sources/Observer.swift; sourceTree = ""; }; - 5030F477E12364AAE5532F5BE20AE54E /* NSObject+BindingTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+BindingTarget.swift"; path = "ReactiveCocoa/NSObject+BindingTarget.swift"; sourceTree = ""; }; - 50D246C696E1D1DDD1F8545492DE9F95 /* SDWebImageDecoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDecoder.m; path = SDWebImage/SDWebImageDecoder.m; sourceTree = ""; }; - 511961DB43E641DA6E916E03D4AD14F4 /* Schema.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Schema.swift; path = RealmSwift/Schema.swift; sourceTree = ""; }; - 512B9A5158A40CEC213006BE06F53315 /* UIRefreshControl.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIRefreshControl.swift; path = ReactiveCocoa/UIKit/iOS/UIRefreshControl.swift; sourceTree = ""; }; - 5131C2AB4E890595679303AA065FC3B4 /* Runes-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Runes-prefix.pch"; sourceTree = ""; }; - 52653314A619A2302BEDBD734F4F9F36 /* results.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = results.cpp; path = Realm/ObjectStore/src/results.cpp; sourceTree = ""; }; - 5271EC894F3143DFB2B40E1F8339F726 /* QuickSelectedTestSuiteBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = QuickSelectedTestSuiteBuilder.swift; path = Sources/Quick/QuickSelectedTestSuiteBuilder.swift; sourceTree = ""; }; - 5307203EC65D843D6218225D81406D62 /* NSData+ImageContentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+ImageContentType.h"; path = "SDWebImage/NSData+ImageContentType.h"; sourceTree = ""; }; - 53096508F660433426E57D71FA76C816 /* transact_log_handler.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = transact_log_handler.cpp; path = Realm/ObjectStore/src/impl/transact_log_handler.cpp; sourceTree = ""; }; - 542C83EC4E362B1E4036EDB131C4B2CE /* NSObject+ObjCRuntime.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+ObjCRuntime.swift"; path = "ReactiveCocoa/NSObject+ObjCRuntime.swift"; sourceTree = ""; }; - 54DA9444F1ED16C10D04D55654096038 /* Contain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Contain.swift; path = Sources/Nimble/Matchers/Contain.swift; sourceTree = ""; }; - 54E89418684BB6D4571366C9D27F6AAE /* Callsite.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Callsite.swift; path = Sources/Quick/Callsite.swift; sourceTree = ""; }; - 555BC55AF5CF61AC1064B2BA8B77D5B9 /* World.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = World.h; path = Sources/QuickObjectiveC/World.h; sourceTree = ""; }; - 5573F218EC3FDDACDF98B941DAB1A9CE /* SDWebImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloader.m; path = SDWebImage/SDWebImageDownloader.m; sourceTree = ""; }; - 55EF9D5B346E69E9CFF60DDC13761112 /* UIImage+GIF.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+GIF.h"; path = "SDWebImage/UIImage+GIF.h"; sourceTree = ""; }; - 5632D95E55EEE3F8E42F36694AA3C8F6 /* Curry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Curry-prefix.pch"; sourceTree = ""; }; - 564DF2424B8E212FED546E5CF3D4DEC9 /* RLMUpdateChecker.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMUpdateChecker.mm; path = Realm/RLMUpdateChecker.mm; sourceTree = ""; }; - 583DFEF3167808DBE921F927EC0647D5 /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlBadInstructionException.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift; sourceTree = ""; }; - 585421F892EECE0D46E02A75FADF3D32 /* SDWebImageDownloaderOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageDownloaderOperation.m; path = SDWebImage/SDWebImageDownloaderOperation.m; sourceTree = ""; }; - 588716E07AB61E12616DE68E22140115 /* RLMObjectBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectBase.mm; path = Realm/RLMObjectBase.mm; sourceTree = ""; }; - 5953293A5C09A44DF3E762819A0D6161 /* placeholder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = placeholder.cpp; path = Realm/ObjectStore/src/placeholder.cpp; sourceTree = ""; }; - 5956ED9D5D7E478706DC7E2A5E06C24B /* AdapterProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdapterProtocols.swift; path = Sources/Nimble/Adapters/AdapterProtocols.swift; sourceTree = ""; }; - 59733EB1ABE53D9A3DFD27170F416260 /* index_set.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = index_set.cpp; path = Realm/ObjectStore/src/index_set.cpp; sourceTree = ""; }; - 597631411F419DF710CD14B247BB2214 /* CwlCatchException.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = CwlCatchException.m; path = Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m; sourceTree = ""; }; - 59AC20E6AC41358A4AE618014B5DE572 /* RLMMigration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMMigration.mm; path = Realm/RLMMigration.mm; sourceTree = ""; }; - 59D6B728F4B5D6683F3879D7DDA63938 /* Realm-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Realm-dummy.m"; sourceTree = ""; }; - 5A084AD5E025AAF2890332298FD0D304 /* ReactiveCocoa.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ReactiveCocoa.xcconfig; sourceTree = ""; }; - 5A8C6A2BCD4DC200FF37D71F8703A4BC /* Marshal.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Marshal.modulemap; sourceTree = ""; }; - 5AF744E9747D20F1326DA20382BB8FE4 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5B1AC27116D413175DD38E2EDF04552C /* CwlCatchBadInstruction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CwlCatchBadInstruction.h; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h; sourceTree = ""; }; - 5BAFEAED1D1237AB634CF4E6CFF8CAE7 /* RLMAuthResponseModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMAuthResponseModel.m; path = Realm/RLMAuthResponseModel.m; sourceTree = ""; }; - 5CFBECA7EDBB969B477538958A4E4B2D /* Quick.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Quick.h; path = Sources/QuickObjectiveC/Quick.h; sourceTree = ""; }; - 5E0BBF837B9CC5EDE662153D4FED782F /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Sources/Nimble/DSL.swift; sourceTree = ""; }; - 60137E489216AC88928F589F37AC26EF /* RealmSwift-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RealmSwift-prefix.pch"; sourceTree = ""; }; - 6039C57D15D206D596DA022F2D775651 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 607DBEB86A79A5476B63B37A8059F2AA /* QCKDSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QCKDSL.m; path = Sources/QuickObjectiveC/DSL/QCKDSL.m; sourceTree = ""; }; - 60A002572AC20E5406A90AAC57DFF042 /* RLMOptionalBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMOptionalBase.h; path = include/RLMOptionalBase.h; sourceTree = ""; }; - 60E31CE3FBB85A560035ACF301565420 /* RLMSyncManager_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncManager_Private.h; path = include/RLMSyncManager_Private.h; sourceTree = ""; }; - 6182E9EC62179AFCE72E2ED9B9E2F0D9 /* ReactiveSwift.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ReactiveSwift.xcconfig; sourceTree = ""; }; - 6215008A04F973F0AE63DD326BD1C487 /* BeginWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeginWith.swift; path = Sources/Nimble/Matchers/BeginWith.swift; sourceTree = ""; }; - 6400A354816834BB21D4290FA9222D2B /* Result-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Result-umbrella.h"; sourceTree = ""; }; - 64BA96A52A8B3B259F42459013F60BE8 /* RLMObservation.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObservation.mm; path = Realm/RLMObservation.mm; sourceTree = ""; }; - 64D4DAB0875793978F8CC3CBFADBCC0D /* RLMSyncErrorResponseModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncErrorResponseModel.m; path = Realm/RLMSyncErrorResponseModel.m; sourceTree = ""; }; - 6508E193CF684DA6CB3E037900D61985 /* SDWebImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloader.h; path = SDWebImage/SDWebImageDownloader.h; sourceTree = ""; }; - 650E1C42F742EC5169024DDB0261F042 /* Quick-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Quick-prefix.pch"; sourceTree = ""; }; - 660B1F6A04701B2F3FF99A48AAD00CDC /* Flatten.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Flatten.swift; path = Sources/Flatten.swift; sourceTree = ""; }; - 66A50B6824BF89D3C2F70DBAB43184CA /* Reachability.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Reachability.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 678DB41814A5FDAC91F12190877D99F4 /* NSData+ImageContentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+ImageContentType.m"; path = "SDWebImage/NSData+ImageContentType.m"; sourceTree = ""; }; - 67DB0CBF7F97920F9ABEFC7BC7BE9DA3 /* RLMArray.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray.h; path = include/RLMArray.h; sourceTree = ""; }; - 67ED53E6A7BAEC9E2A57E18D07095477 /* SDWebImage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = SDWebImage.modulemap; sourceTree = ""; }; - 68CFF6EA076886323E883D239FC2D72F /* WebKitExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WebKitExtensions.swift; sourceTree = ""; }; - 69521AAD7D6505125DEA62C9B1AC7B2A /* FailureMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FailureMessage.swift; path = Sources/Nimble/FailureMessage.swift; sourceTree = ""; }; - 6A1A26B81673A0FA39FB285C2142D4A8 /* Event.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Event.swift; path = Sources/Event.swift; sourceTree = ""; }; - 6A33FB7ED3C98C702DBA6A53A8A1D633 /* keychain_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = keychain_helper.cpp; path = Realm/ObjectStore/src/impl/apple/keychain_helper.cpp; sourceTree = ""; }; - 6ADBEE110332037CCF4855CB62C96890 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6B0447391FF479F0CF5C4AC6BE28E798 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6B0E4E4C02341EF78603E824B2733137 /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = Sources/Optional.swift; sourceTree = ""; }; - 6B2E01CA5514B90525ECF3E081451287 /* NimbleEnvironment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NimbleEnvironment.swift; path = Sources/Nimble/Adapters/NimbleEnvironment.swift; sourceTree = ""; }; - 6B4B4D235F8BAAE064E0DFCC37393113 /* RLMRealm_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Dynamic.h; path = include/RLMRealm_Dynamic.h; sourceTree = ""; }; - 6BD95C70957EA9EA4B65B2D724C34C0E /* SDWebImageDownloaderOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageDownloaderOperation.h; path = SDWebImage/SDWebImageDownloaderOperation.h; sourceTree = ""; }; - 6C206A1AEEA9ABF086EFA4DB5A915A02 /* MatchError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatchError.swift; path = Sources/Nimble/Matchers/MatchError.swift; sourceTree = ""; }; - 6EE4CFE17744FA0B4EE48863BB8E6C0C /* NMBExceptionCapture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NMBExceptionCapture.h; path = Sources/NimbleObjectiveC/NMBExceptionCapture.h; sourceTree = ""; }; - 6F298A6855749549EF58B48DBA763B3F /* BeAKindOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAKindOf.swift; path = Sources/Nimble/Matchers/BeAKindOf.swift; sourceTree = ""; }; - 7008F7E5A7BC03218B8379B5924B5CAB /* Match.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Match.swift; path = Sources/Nimble/Matchers/Match.swift; sourceTree = ""; }; - 7087BC923ECE8A70F3168A6EF38FE9E4 /* UnidirectionalBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UnidirectionalBinding.swift; path = Sources/UnidirectionalBinding.swift; sourceTree = ""; }; - 7097638BF5C5369199675574769441C3 /* SourceLocation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceLocation.swift; path = Sources/Nimble/Utils/SourceLocation.swift; sourceTree = ""; }; - 7105FDADD9F5EA077FCF4AB41527F29A /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AsyncMatcherWrapper.swift; path = Sources/Nimble/Matchers/AsyncMatcherWrapper.swift; sourceTree = ""; }; - 712808AA58D0CF2BE85538F15BA355BB /* Pods-ACKReactiveExtensions_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ACKReactiveExtensions_Example-umbrella.h"; sourceTree = ""; }; - 718DF05EBBCB9BDE444E6A5537C11253 /* CocoaTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CocoaTarget.swift; path = ReactiveCocoa/CocoaTarget.swift; sourceTree = ""; }; - 721752886DA62F718878703E4387C37B /* Alternative.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alternative.swift; path = Sources/Argo/Types/Decoded/Alternative.swift; sourceTree = ""; }; - 7222A864F00CCFD6624F1E635745EF2F /* UIScrollView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIScrollView.swift; path = ReactiveCocoa/UIKit/UIScrollView.swift; sourceTree = ""; }; - 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 7335FCB18987188E521D2CB4729E488B /* Functor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Functor.swift; path = Sources/Argo/Types/Decoded/Functor.swift; sourceTree = ""; }; - 73AE9B430B7AAACCF9A62DA30EA4131D /* Quick-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Quick-dummy.m"; sourceTree = ""; }; - 7405112230B30EF773FD16BD6C3F6BFE /* ACKReactiveExtensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ACKReactiveExtensions.framework; path = ACKReactiveExtensions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7491821E2D46EE33A835436948D1D049 /* Reachability.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; - 755B77B525264DCF0FAD386170A1DEB8 /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ReactiveSwift.framework; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7680BAC933258EEFB43803FE7F3B4BA9 /* ExampleHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleHooks.swift; path = Sources/Quick/Hooks/ExampleHooks.swift; sourceTree = ""; }; - 76E1482324EF76467354EBCD9556D5C3 /* NSString+QCKSelectorName.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+QCKSelectorName.m"; path = "Sources/QuickObjectiveC/NSString+QCKSelectorName.m"; sourceTree = ""; }; - 770F024D0C91568CD8662CF31067A2D0 /* Marshal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Marshal.framework; path = Marshal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7750B0A880CBB6D5D731191421BC46FF /* Object.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Object.swift; path = RealmSwift/Object.swift; sourceTree = ""; }; - 776B847D8D6EBDA487170EA134742F04 /* Argo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Argo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 788E044960791E209D43E3E6104BA2CC /* ReusableComponents.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ReusableComponents.swift; path = ReactiveCocoa/UIKit/ReusableComponents.swift; sourceTree = ""; }; - 78D56E6C8D49BE35A469566AD3FB1761 /* BeEmpty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeEmpty.swift; path = Sources/Nimble/Matchers/BeEmpty.swift; sourceTree = ""; }; - 7926680981FA4A7419448AD54A1843F8 /* Curry.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Curry.modulemap; sourceTree = ""; }; - 7933A983C1B0B4BC46FB1FC2C3BDDD66 /* RLMProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty.h; path = include/RLMProperty.h; sourceTree = ""; }; - 797DA5F71FF30F1F36CB728EA07D86CE /* ValueType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ValueType.swift; path = Sources/ValueType.swift; sourceTree = ""; }; - 79AD58BD3EBDD205E05F8B3706FBB64D /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; - 79BA6850B472A54BE2BA2ACA3DD0D230 /* Marshal-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Marshal-prefix.pch"; sourceTree = ""; }; - 79E8CB9721CAD2839C372D9DBF7DAF3F /* decode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = decode.swift; path = Sources/Argo/Functions/decode.swift; sourceTree = ""; }; - 7A4E14923BB45C7CE2295CAD3C4D2A0A /* NSLayoutConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSLayoutConstraint.swift; path = ReactiveCocoa/Shared/NSLayoutConstraint.swift; sourceTree = ""; }; - 7AAE65A0CE34A217C207333F15D71AB4 /* UITableView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UITableView.swift; path = ReactiveCocoa/UIKit/UITableView.swift; sourceTree = ""; }; - 7AD26234BEAE0119C20BE4064E6D1967 /* Reachability.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; - 7B029BDAAC30411CD158C72947848BD8 /* Marshal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Marshal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B5DD5F72AFCC0E16F032E9427520111 /* Reachability.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Reachability.modulemap; sourceTree = ""; }; - 7B82C0D57E8ED3BBF27CBF4EF355DA41 /* UISegmentedControl.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UISegmentedControl.swift; path = ReactiveCocoa/UIKit/UISegmentedControl.swift; sourceTree = ""; }; - 7CB9A2CC4443A5D98CC7C8883879D405 /* Curry-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Curry-umbrella.h"; sourceTree = ""; }; - 7CDC63EAB2558BED1B47A3463C271EF3 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NMBObjCMatcher.swift; path = Sources/Nimble/Adapters/NMBObjCMatcher.swift; sourceTree = ""; }; - 7E0C2146E06F8FE932AAC749F843932D /* Migration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Migration.swift; path = Sources/Migration.swift; sourceTree = ""; }; - 7EA57594A19435F5B4B1409AB307B27A /* ThrowError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThrowError.swift; path = Sources/Nimble/Matchers/ThrowError.swift; sourceTree = ""; }; - 8004AF76C027BB4EBA37A5052DA1477C /* results_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = results_notifier.cpp; path = Realm/ObjectStore/src/impl/results_notifier.cpp; sourceTree = ""; }; - 803396491622E4B64777359DFE9C44FB /* sync_metadata.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_metadata.cpp; path = Realm/ObjectStore/src/sync/impl/sync_metadata.cpp; sourceTree = ""; }; - 8069B37F697707BB94630A7CFF7465E3 /* Disposable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = Sources/Disposable.swift; sourceTree = ""; }; - 82D2257099413C297FBE7E94B01F5DEA /* RLMSyncSession.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncSession.mm; path = Realm/RLMSyncSession.mm; sourceTree = ""; }; - 839C4A8D444DC868D4C610DE4723D033 /* RLMObjectSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectSchema.mm; path = Realm/RLMObjectSchema.mm; sourceTree = ""; }; - 83A979E39ECA440AAF10D35FD95D0108 /* CwlCatchBadInstruction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = CwlCatchBadInstruction.m; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m; sourceTree = ""; }; - 83DA572BDB4AE6A871F42422970968DC /* RLMRealmConfiguration+Sync.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RLMRealmConfiguration+Sync.h"; path = "include/RLMRealmConfiguration+Sync.h"; sourceTree = ""; }; - 85FB91F281737568C40E1BE91EC624BE /* RLMObjectSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema.h; path = include/RLMObjectSchema.h; sourceTree = ""; }; - 86FC0E79C1FE92FB2234ADB0BE668E87 /* ErrorUtility.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ErrorUtility.swift; path = Sources/Quick/ErrorUtility.swift; sourceTree = ""; }; - 88FCD6FA8617AC21FC97DBD75A967F5A /* Decodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Decodable.swift; path = Sources/Argo/Types/Decodable.swift; sourceTree = ""; }; - 8973670C4D50F686E0A23EC6A97FBA02 /* StandardTypes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StandardTypes.swift; path = Sources/Argo/Types/StandardTypes.swift; sourceTree = ""; }; - 89BE574C4E94967835529C99140316AE /* SDImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCache.h; path = SDWebImage/SDImageCache.h; sourceTree = ""; }; - 89C8A2C1910B3237CCE7496E88D0999F /* Nimble-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Nimble-prefix.pch"; sourceTree = ""; }; - 89F1EE46FE6D88D9792F383AF2EE5E79 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThanOrEqual.swift; path = Sources/Nimble/Matchers/BeLessThanOrEqual.swift; sourceTree = ""; }; - 8A4BD9BF1A83C0E6C3FABF55C75DC471 /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CwlCatchBadInstruction.swift; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift; sourceTree = ""; }; - 8B7379B6BEAA2C66A9A218110F722599 /* Curry.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Curry.xcconfig; sourceTree = ""; }; - 8BAEF129B05502833A3C38D1187D1F7B /* Reachability.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Reachability.xcconfig; sourceTree = ""; }; - 8E38F0DF683B927E30C0D6581557086D /* Pods-ACKReactiveExtensions_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ACKReactiveExtensions_Example-dummy.m"; sourceTree = ""; }; - 8E4922058ED17F1F12A2D8541AF8AD34 /* Quick.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Quick.modulemap; sourceTree = ""; }; - 8E8CE214B1B86DA92092AE2CAA9E7725 /* RLMAnalytics.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMAnalytics.mm; path = Realm/RLMAnalytics.mm; sourceTree = ""; }; - 8EDC7231C6D843E39DC3BD8D5B07DCEA /* Runes.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Runes.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8F676FA1A07445F3F1211E9D7D5FF126 /* Pods-ACKReactiveExtensions_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ACKReactiveExtensions_Example-resources.sh"; sourceTree = ""; }; - 915588B75D0D58472F979621CB7066B7 /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Sources/Quick/Filter.swift; sourceTree = ""; }; - 915E2130F82FBCD696E7B41FD2255114 /* UIButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIButton.swift; path = ReactiveCocoa/UIKit/UIButton.swift; sourceTree = ""; }; - 91BB85FE67400DD1B6A46E08596D0760 /* RLMConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMConstants.h; path = include/RLMConstants.h; sourceTree = ""; }; - 91CE2BD9967BB2A97F75D2501EA5D3A2 /* Core.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = ""; }; - 9219C02824374A414928D9E2AC846ACF /* RLMSyncPermissionChange_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncPermissionChange_Private.h; path = include/RLMSyncPermissionChange_Private.h; sourceTree = ""; }; - 9303ABBB4DD1AC4EFC6B839FB06EA148 /* mach_excServer.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mach_excServer.c; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c; sourceTree = ""; }; - 9329FB7EF8E0C35A84BFAB0448E91888 /* Unmarshaling.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Unmarshaling.swift; path = Sources/Unmarshaling.swift; sourceTree = ""; }; - 9397232493D47E251FCD38B034EF4755 /* RLMObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject.h; path = include/RLMObject.h; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9441F22F2A6487F20303AD5F44F9AD34 /* UISearchBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UISearchBar.swift; path = ReactiveCocoa/UIKit/iOS/UISearchBar.swift; sourceTree = ""; }; - 9447ABB644366BA6F61BEF379830782A /* Deprecations.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Deprecations.swift; sourceTree = ""; }; - 95285970C9E3D84B94D81925791804BF /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 963BB70A82BFE7020C9EC5647DD540FC /* Example.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Example.swift; path = Sources/Quick/Example.swift; sourceTree = ""; }; - 966BAD0CEA9341185E138C46BDC13777 /* RLMPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMPlatform.h; path = include/RLMPlatform.h; sourceTree = ""; }; - 96A1D01AD61167F40E747F4BA875E5B4 /* UIControl.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIControl.swift; path = ReactiveCocoa/UIKit/UIControl.swift; sourceTree = ""; }; - 97500615959F3658229E0B487EA37835 /* realm_coordinator.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = realm_coordinator.cpp; path = Realm/ObjectStore/src/impl/realm_coordinator.cpp; sourceTree = ""; }; - 979DECF18FE73967EBA41B3938401CA8 /* RLMSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema.h; path = include/RLMSchema.h; sourceTree = ""; }; - 991B28D558F7F4AB0752F5EDF23FEE75 /* ACKReactiveExtensions-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ACKReactiveExtensions-dummy.m"; sourceTree = ""; }; - 9A77A4C2A72C73B57B3099B36D9B02BA /* NSString+QCKSelectorName.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+QCKSelectorName.h"; path = "Sources/QuickObjectiveC/NSString+QCKSelectorName.h"; sourceTree = ""; }; - 9DC1BCD07008B3D42C609AE5328DCB8C /* RLMSyncUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil.h; path = include/RLMSyncUtil.h; sourceTree = ""; }; - 9E16D1C7108C92F7132BFE96188F7AD2 /* ReactiveCocoa.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ReactiveCocoa.h; path = ReactiveCocoa/ReactiveCocoa.h; sourceTree = ""; }; - 9EB31B26BDDC740A81CB05AD0E163BDA /* Closures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Closures.swift; path = Sources/Quick/Hooks/Closures.swift; sourceTree = ""; }; - 9F4C34DBECC5FC8CDC1A5D97DFC0095A /* RLMRealm_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Private.h; path = include/RLMRealm_Private.h; sourceTree = ""; }; - 9FAE2BA55456042322852F0EBA66E3E2 /* ExampleGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleGroup.swift; path = Sources/Quick/ExampleGroup.swift; sourceTree = ""; }; - A00AAA4C6E10464A3405F98A180C3FB0 /* XCTestObservationCenter+Register.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "XCTestObservationCenter+Register.m"; path = "Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m"; sourceTree = ""; }; - A01AEAB1941A302C8B6218CE188443B0 /* sync_session.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_session.cpp; path = Realm/ObjectStore/src/sync/sync_session.cpp; sourceTree = ""; }; - A04C8302566928C5C225A03FAF0C7875 /* Pods-ACKReactiveExtensions_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ACKReactiveExtensions_Example-acknowledgements.markdown"; sourceTree = ""; }; - A05B079F9AD843FA9C72FF8899904B85 /* String+FileName.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+FileName.swift"; path = "Sources/Quick/String+FileName.swift"; sourceTree = ""; }; - A0F59BF4AD6298FBBDEF7F8FFC6E2DFC /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = Sources/Optional.swift; sourceTree = ""; }; - A1037624D3A582BEEB81981869141420 /* QuickConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickConfiguration.h; path = Sources/QuickObjectiveC/Configuration/QuickConfiguration.h; sourceTree = ""; }; - A214C3E3D297146D4D0989B560A957F5 /* Result-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Result-prefix.pch"; sourceTree = ""; }; - A21F857CC9433B920B0AB4D045D27935 /* BeGreaterThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThan.swift; path = Sources/Nimble/Matchers/BeGreaterThan.swift; sourceTree = ""; }; - A2AECBA86246CF8C0DCAE070D4A3BB8A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A347A88FAFBC3EF3A8473E08354ADC1E /* UIView+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCache.h"; path = "SDWebImage/UIView+WebCache.h"; sourceTree = ""; }; - A39C238E75ECD4C8358AF6078BEEF931 /* Nimble.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Nimble.xcconfig; sourceTree = ""; }; - A516F7D84ED85B2E9DECFBB69017DDD1 /* MarshalMapping.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MarshalMapping.swift; sourceTree = ""; }; - A5A9D071939A19BBD61396BB404F35FF /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.modulemap"; sourceTree = ""; }; - A5B16B462FDEFE1759C0D8EAE416E19E /* BeNil.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeNil.swift; path = Sources/Nimble/Matchers/BeNil.swift; sourceTree = ""; }; - A6343B009137DD1A99C70E4FEDC837E3 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCacheOperation.h"; path = "SDWebImage/UIView+WebCacheOperation.h"; sourceTree = ""; }; - A6D3216BE419DC5864B02E6F2201C034 /* RLMListBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMListBase.h; path = include/RLMListBase.h; sourceTree = ""; }; - A7DDC7C79747E06F695CFE767BF514FC /* RLMQueryUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMQueryUtil.mm; path = Realm/RLMQueryUtil.mm; sourceTree = ""; }; - A8907DBAC4A353CD157422CC1361BE27 /* Array.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Array.swift; path = Sources/Array.swift; sourceTree = ""; }; - A8FE40626F29606EE28AF5449B7B14CD /* ACKReactiveExtensions.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ACKReactiveExtensions.xcconfig; sourceTree = ""; }; - A901B8CEB82AF015D61F999D5A7E8D71 /* RLMAccessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMAccessor.h; path = include/RLMAccessor.h; sourceTree = ""; }; - AA8B42E70E3399E2D9030DDA7AB81DF1 /* HooksPhase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HooksPhase.swift; path = Sources/Quick/Hooks/HooksPhase.swift; sourceTree = ""; }; - AA9436789E37E80359F8A2176F388D3B /* RLMObjectBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase.h; path = include/RLMObjectBase.h; sourceTree = ""; }; - AACEA0B58AD6F1E95023ABD1DB5262F2 /* SDWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageOperation.h; path = SDWebImage/SDWebImageOperation.h; sourceTree = ""; }; - AC256ADDA6D2D62C6DD213773A7D60BE /* NSObject+ReactiveExtensionsProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+ReactiveExtensionsProvider.swift"; path = "ReactiveCocoa/NSObject+ReactiveExtensionsProvider.swift"; sourceTree = ""; }; - AC25F299AE01ECBE0FA85A2645691649 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.plist"; sourceTree = ""; }; - AC757E793AB194E266338F08E1E2C0F4 /* Pods-ACKReactiveExtensions_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ACKReactiveExtensions_Example-acknowledgements.plist"; sourceTree = ""; }; - AC9EF25517ED5300468609A48031872D /* RLMSyncCredentials.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncCredentials.h; path = include/RLMSyncCredentials.h; sourceTree = ""; }; - AE00E475E56003AD4B4A2AEE0DE038EA /* QuickSpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickSpec.m; path = Sources/QuickObjectiveC/QuickSpec.m; sourceTree = ""; }; - AE079783607F84C877F15ED9EB6260EF /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MultiFormat.m"; path = "SDWebImage/UIImage+MultiFormat.m"; sourceTree = ""; }; - AE0F8E56CD72C260B37D78AB6061F35F /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m"; sourceTree = ""; }; - AEDF0E9F5960B84839C674C69004405F /* RLMOptionalBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMOptionalBase.mm; path = Realm/RLMOptionalBase.mm; sourceTree = ""; }; - AF09F3100D0F9E7D24B84A1BF0700FE1 /* Nimble-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Nimble-dummy.m"; sourceTree = ""; }; - AF28C6F7F43248012239061C17517C4F /* Async.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Async.swift; path = Sources/Nimble/Utils/Async.swift; sourceTree = ""; }; - AF4D7C33BF3FCD7F5980750DFE079618 /* RLMRealmConfiguration+Sync.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = "RLMRealmConfiguration+Sync.mm"; path = "Realm/RLMRealmConfiguration+Sync.mm"; sourceTree = ""; }; - B11C4A93148054BB7AC617A782F1B743 /* Result.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Result.xcconfig; sourceTree = ""; }; - B1D795BFC1FB929416B4C0C3D2D66E5C /* Argo.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Argo.xcconfig; sourceTree = ""; }; - B2E943780D14D82033A5A724B6B18E47 /* CurrentTestCaseTracker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CurrentTestCaseTracker.h; path = Sources/NimbleObjectiveC/CurrentTestCaseTracker.h; sourceTree = ""; }; - B2FE7CF151309D9D3878192E09F3A3FF /* ReactiveSwift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ReactiveSwift-dummy.m"; sourceTree = ""; }; - B382581DC6AB3FAD73955AE651D3AB2A /* RLMPredicateUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMPredicateUtil.mm; path = Realm/RLMPredicateUtil.mm; sourceTree = ""; }; - B3E17E98C83930E4548DECCCCE0E0F48 /* ACKReactiveExtensions-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ACKReactiveExtensions-prefix.pch"; sourceTree = ""; }; - B4B1E8C437B59066AD9B23630A086B09 /* schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = schema.cpp; path = Realm/ObjectStore/src/schema.cpp; sourceTree = ""; }; - B4DB6173F603EAE2C38283B1018FE1AD /* RLMSyncUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUser.h; path = include/RLMSyncUser.h; sourceTree = ""; }; - B4F88E0FF65CF094BD268C7C6D05A892 /* UITextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UITextView.swift; path = ReactiveCocoa/UIKit/UITextView.swift; sourceTree = ""; }; - B4F914D5FC0B1958CA70FE28F125D23A /* Curry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Curry-dummy.m"; sourceTree = ""; }; - B6400103CC33210C1B50120D98BE83F0 /* DecodeError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DecodeError.swift; path = Sources/Argo/Types/DecodeError.swift; sourceTree = ""; }; - B677F06DEB90ACF09C4C2C2E387E24A1 /* NSObject+Intercepting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+Intercepting.swift"; path = "ReactiveCocoa/NSObject+Intercepting.swift"; sourceTree = ""; }; - B6839FFD4AAD85B7EDA4F229E6AF9E63 /* Realm.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Realm.modulemap; sourceTree = ""; }; - B736AFE30B4A49758F137F1A60E57887 /* Reachability-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Reachability-dummy.m"; sourceTree = ""; }; - B7807DA6E11433098395A6E72530968A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B8F5CA7E198B6B863E097683798AE42A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B99B990B81693D607321364CAD6D517D /* Pods-ACKReactiveExtensions_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ACKReactiveExtensions_Example.debug.xcconfig"; sourceTree = ""; }; - B9C086F9429415130B95A4D9BD539C4A /* RLMMigration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration_Private.h; path = include/RLMMigration_Private.h; sourceTree = ""; }; - BA20BBD149564311AB716616EA39EEA6 /* DelegateProxy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DelegateProxy.swift; path = ReactiveCocoa/DelegateProxy.swift; sourceTree = ""; }; - BACBB011CA1C6A70A56074BE121474A3 /* Atomic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Atomic.swift; path = Sources/Atomic.swift; sourceTree = ""; }; - BD8908482E11690C4B6D21DFDDF4B4A9 /* DSL+Wait.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DSL+Wait.swift"; path = "Sources/Nimble/DSL+Wait.swift"; sourceTree = ""; }; - BDB9157B69478671E392C9CF309B1BBD /* RLMSyncConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration.h; path = include/RLMSyncConfiguration.h; sourceTree = ""; }; - BDE33B4567F08D97022ECC20CD08799C /* ReactiveCocoa-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ReactiveCocoa-dummy.m"; sourceTree = ""; }; - BE07F2CED458B99C1A99A2A00AADF567 /* collection_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_notifier.cpp; path = Realm/ObjectStore/src/impl/collection_notifier.cpp; sourceTree = ""; }; - BF6AFC9457459627BE4924716346183F /* Signal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Signal.swift; path = Sources/Signal.swift; sourceTree = ""; }; - BF9A947BEFF9F3189347064BED68765E /* Result.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Result.modulemap; sourceTree = ""; }; - BFBCA3AA47952AF10E6F190ED5CDE623 /* UIButton+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+WebCache.h"; path = "SDWebImage/UIButton+WebCache.h"; sourceTree = ""; }; - BFCFC133BE9AF98413824FD3CCEE0BB7 /* RealmSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = RealmSwift.framework; path = RealmSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BFE4C4809982D8B2B4E0E32574AF0D2C /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = RealmSwift/Error.swift; sourceTree = ""; }; - C09657AF9A1B91C4D3AEDB678B9BEAD0 /* RLMRealmConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration_Private.h; path = include/RLMRealmConfiguration_Private.h; sourceTree = ""; }; - C1215503EE4CF7889907BA3EF98947F5 /* ResultProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResultProtocol.swift; path = Result/ResultProtocol.swift; sourceTree = ""; }; - C19BB8E3DD4444877056C7DCE534C187 /* ReactiveCocoa-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ReactiveCocoa-prefix.pch"; sourceTree = ""; }; - C2123A0484B67CA9CC476814C0120E75 /* RLMSyncConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration_Private.h; path = include/RLMSyncConfiguration_Private.h; sourceTree = ""; }; - C2CB229C70353D865CBCDCD994B056AA /* ACKReactiveExtensions-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ACKReactiveExtensions-umbrella.h"; sourceTree = ""; }; - C3D20A0139A53C62A3196A015F501A35 /* Result-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Result-dummy.m"; sourceTree = ""; }; - C44099F5B5E37BEA688D0CDA2A9E3690 /* Argo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Argo.framework; path = Argo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C473DA61E0BF8FC1FA2051931C41EDDE /* UIImageView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/UIImageView+WebCache.m"; sourceTree = ""; }; - C47E6B078EDD964EAC0106763ABCCCE4 /* QuickTestSuite.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = QuickTestSuite.swift; path = Sources/Quick/QuickTestSuite.swift; sourceTree = ""; }; - C4817823CC44D88678A94F02F15DE1CC /* NSObject+Synchronizing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+Synchronizing.swift"; path = "ReactiveCocoa/NSObject+Synchronizing.swift"; sourceTree = ""; }; - C4A7A857A352C067C32F07E9DED5F857 /* RLMObjectSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema_Private.h; path = include/RLMObjectSchema_Private.h; sourceTree = ""; }; - C4F93A29DAA06C2D060AB252DB6933C6 /* UIImage+GIF.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+GIF.m"; path = "SDWebImage/UIImage+GIF.m"; sourceTree = ""; }; - C5062007710E1BEE91B95001D87473D2 /* object_store.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = object_store.cpp; path = Realm/ObjectStore/src/object_store.cpp; sourceTree = ""; }; - C5AD5CA181843E2D59C76185F9F9166A /* NMBStringify.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NMBStringify.h; path = Sources/NimbleObjectiveC/NMBStringify.h; sourceTree = ""; }; - C5F32DF751D97190D3F56A0809955BAC /* NSNumber.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSNumber.swift; path = Sources/Argo/Extensions/NSNumber.swift; sourceTree = ""; }; - C5FCFC7C955830E67FEC0C8844B49590 /* TupleExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TupleExtensions.swift; path = Sources/TupleExtensions.swift; sourceTree = ""; }; - C6239884AFE3DC00BD7C49C2EFD25B46 /* ArgoMapping.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ArgoMapping.swift; sourceTree = ""; }; - C63A2CD4F2A7F04523574F9DD1199A3C /* MarshaledObject.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarshaledObject.swift; path = Sources/MarshaledObject.swift; sourceTree = ""; }; - C72897D5228D7E9D0CA2BCF625481E0D /* CocoaAction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CocoaAction.swift; path = ReactiveCocoa/CocoaAction.swift; sourceTree = ""; }; - C83184A660ADDBE83E50CB93257B58CD /* Realm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Realm.h; path = include/Realm.h; sourceTree = ""; }; - C8F52136FC50F5C79B01F64DDC695D94 /* UICollectionView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UICollectionView.swift; path = ReactiveCocoa/UIKit/UICollectionView.swift; sourceTree = ""; }; - C95B66D60B294D43AF10B595F8B854CD /* Argo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Argo-umbrella.h"; sourceTree = ""; }; - C965627E2D5F1E9A4CF94AD8CEC1A480 /* RLMSyncSessionRefreshHandle.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncSessionRefreshHandle.mm; path = Realm/RLMSyncSessionRefreshHandle.mm; sourceTree = ""; }; - C9E26FF43730A8196ED8C6D674CA0ED2 /* Pods_ACKReactiveExtensions_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_ACKReactiveExtensions_Example.framework; path = "Pods-ACKReactiveExtensions_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - CA1B02C1EEE359F771F58A0FEE948908 /* UIView+WebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+WebCache.m"; path = "SDWebImage/UIView+WebCache.m"; sourceTree = ""; }; - CAD193490FD0DBB2F2D5487F16FECFCE /* RLMConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMConstants.m; path = Realm/RLMConstants.m; sourceTree = ""; }; - CB26D6189CB7AC7831B83F105859FABA /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CB3B717D0FF7591F99AE31AA779EE817 /* Pods-ACKReactiveExtensions_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-ACKReactiveExtensions_Example.modulemap"; sourceTree = ""; }; - CC575AC39BE285B18F0872ABD0BBF28A /* Reachability.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Reachability.framework; path = Reachability.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CC5BAA85DDD9939DB814BBEB2EEA6B00 /* RLMNetworkClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMNetworkClient.m; path = Realm/RLMNetworkClient.m; sourceTree = ""; }; - CCC0CA1E4D7FCB37BB43C06596770A3C /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.release.xcconfig"; sourceTree = ""; }; - CCD6D21B1824B199A28FD405F7F080B9 /* DSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DSL.h; path = Sources/NimbleObjectiveC/DSL.h; sourceTree = ""; }; - CDE76D1DE6FC0A51387FEF2D10B199EC /* RLMSyncPermissionChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncPermissionChange.m; path = Realm/RLMSyncPermissionChange.m; sourceTree = ""; }; - CE589D63713D983B7A2CC10D113B938D /* Runes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Runes.swift; path = Sources/Runes.swift; sourceTree = ""; }; - CEB9CD136253747ACFF7E6ECE6200A47 /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = RealmSwift/Optional.swift; sourceTree = ""; }; - CEEE75D737864E8B717EE9DAC08740CF /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = Sources/Nimble/Expression.swift; sourceTree = ""; }; - CF292D056F5D302553FC320659C05291 /* NSImage+WebCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSImage+WebCache.h"; path = "SDWebImage/NSImage+WebCache.h"; sourceTree = ""; }; - CF327CD37DCDC6B4C4D9F34962D9CEC5 /* PostNotification.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PostNotification.swift; path = Sources/Nimble/Matchers/PostNotification.swift; sourceTree = ""; }; - CF5A0E74BE0C0E430EE089E1795F92EC /* BeLessThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThan.swift; path = Sources/Nimble/Matchers/BeLessThan.swift; sourceTree = ""; }; - CFBF2C669407931F2E961AB92AEA7F1D /* RLMRealm.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealm.mm; path = Realm/RLMRealm.mm; sourceTree = ""; }; - CFCCDC4D7CE01D0325D2BFC246BDD146 /* RLMSyncManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncManager.h; path = include/RLMSyncManager.h; sourceTree = ""; }; - D06DCE506336E68E74741682FA232A62 /* SDWebImageCompat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImageCompat.h; path = SDWebImage/SDWebImageCompat.h; sourceTree = ""; }; - D0F5AA65BC44CDE9194A8836CB27C67B /* UIKeyboard.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIKeyboard.swift; path = ReactiveCocoa/UIKit/iOS/UIKeyboard.swift; sourceTree = ""; }; - D0FBA9589FAAE69C553734B593FEB496 /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Sources/Nimble/Utils/Errors.swift; sourceTree = ""; }; - D10832EF3E35D8B927A00C7D9AD97AC7 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h"; sourceTree = ""; }; - D25DB37DEC6459819431654AECC624A6 /* UIPickerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIPickerView.swift; path = ReactiveCocoa/UIKit/iOS/UIPickerView.swift; sourceTree = ""; }; - D2ACC5157986C4C2A2BDDEE70753BE4B /* SDImageCacheConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDImageCacheConfig.h; path = SDWebImage/SDImageCacheConfig.h; sourceTree = ""; }; - D2DBF88CB3F9FA28E0C8002374D860DA /* RLMRealmConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration.h; path = include/RLMRealmConfiguration.h; sourceTree = ""; }; - D2F719B9B7093A7E3611B4CBA6D4BD44 /* list.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = list.cpp; path = Realm/ObjectStore/src/list.cpp; sourceTree = ""; }; - D42C961D3D18E87840C227EBD1663227 /* DynamicProperty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DynamicProperty.swift; path = ReactiveCocoa/DynamicProperty.swift; sourceTree = ""; }; - D48CCF27EDBE23C0E6EC0CA035D560C0 /* SortDescriptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SortDescriptor.swift; path = RealmSwift/SortDescriptor.swift; sourceTree = ""; }; - D48FF7D6643A2CA2A68C1C44D2E1C5C8 /* RLMObject_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject_Private.h; path = include/RLMObject_Private.h; sourceTree = ""; }; - D58B017B22770D3C49FB229911CCA63F /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Sources/Quick/Configuration/Configuration.swift; sourceTree = ""; }; - D636D627BCC9BA5B12D79DD65E7E7E63 /* SDWebImage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SDWebImage-umbrella.h"; sourceTree = ""; }; - D76B8505276FA8CA680C74C2BF1FE31C /* UIBarItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIBarItem.swift; path = ReactiveCocoa/UIKit/UIBarItem.swift; sourceTree = ""; }; - D7ADF689A2FEBF5D2B0B97224BE6E39A /* RLMSwiftSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSwiftSupport.m; path = Realm/RLMSwiftSupport.m; sourceTree = ""; }; - D7CBCD6FCBEC9D5717693AB91F54AC96 /* Argo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Argo.swift; path = Sources/Argo/Operators/Argo.swift; sourceTree = ""; }; - D86207497AC6CFA632EC64CB15A5923F /* UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIImageView.swift; path = ReactiveCocoa/UIKit/UIImageView.swift; sourceTree = ""; }; - D887D2D35CA24443E4491D8AB9ABF431 /* Sync.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Sync.swift; path = RealmSwift/Sync.swift; sourceTree = ""; }; - D8D8C1F9916E66215E027888318CD599 /* List.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = List.swift; path = RealmSwift/List.swift; sourceTree = ""; }; - D8F4C0E290ADB2B3B26394BA66CA4385 /* flatReduce.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = flatReduce.swift; path = Sources/Argo/Functions/flatReduce.swift; sourceTree = ""; }; - D9C78D129BD75FF297820F1F1C73A7F6 /* LinkingObjects.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LinkingObjects.swift; path = RealmSwift/LinkingObjects.swift; sourceTree = ""; }; - DAB72ED5D33B92009EA6EDCD838AA5DC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DAD9C8DAF1108DFF164034DBD5137A01 /* RLMSyncCredentials.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncCredentials.m; path = Realm/RLMSyncCredentials.m; sourceTree = ""; }; - DB2110822BD1008D595EA83C92482309 /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+HighlightedWebCache.m"; path = "SDWebImage/UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; - DB81A8BB2D4920F81288AE7615EA7AC1 /* ExampleMetadata.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleMetadata.swift; path = Sources/Quick/ExampleMetadata.swift; sourceTree = ""; }; - DCD5EBA74745951058FAC1CA3A947A45 /* UIView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIView.swift; path = ReactiveCocoa/UIKit/UIView.swift; sourceTree = ""; }; - DD921AE6FCDD0B567642339C85FF7EBB /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SDWebImage.framework; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DDA1C3C2C9C97BC2CC36CC727B5A072D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - DDDFBDC4BDF1483CA04B98A0A2778B67 /* SDWebImagePrefetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImagePrefetcher.m; path = SDWebImage/SDWebImagePrefetcher.m; sourceTree = ""; }; - DE26BE6B3B2A24098629C1CDA4775E7C /* sync_user.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_user.cpp; path = Realm/ObjectStore/src/sync/sync_user.cpp; sourceTree = ""; }; - DEB38EF7525DEC9DF35A2CAB77A89C2A /* Runes.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Runes.modulemap; sourceTree = ""; }; - DEBB70BB0C957EF815DBA5CF04BE6439 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Nimble.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DF14F4BCFCB54C50CC44B9F24A1C06E0 /* RLMMigration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration.h; path = include/RLMMigration.h; sourceTree = ""; }; - DF22416A2052DCD719780514C43D7DD3 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; - DF2759610C450FD80023B3565046245D /* Bag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Bag.swift; path = Sources/Bag.swift; sourceTree = ""; }; - E00F5ECCFE503D51297AAAC62731DB3F /* Argo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Argo-dummy.m"; sourceTree = ""; }; - E01544D39F7477EE1534CC9385D68AC6 /* handover.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = handover.cpp; path = Realm/ObjectStore/src/impl/handover.cpp; sourceTree = ""; }; - E083C71019FF77A198A3A5B6729E9C16 /* Deprecations+Removals.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Deprecations+Removals.swift"; path = "Sources/Deprecations+Removals.swift"; sourceTree = ""; }; - E1496F2101AA68CBAF4B9E8ECBA7FBC6 /* BeLogical.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLogical.swift; path = Sources/Nimble/Matchers/BeLogical.swift; sourceTree = ""; }; - E1ABBE197ADEF9C7B459DCBAA0430C87 /* KeyType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KeyType.swift; path = Sources/KeyType.swift; sourceTree = ""; }; - E2150184B2621EB4006941B2B9094AB1 /* shared_realm.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = shared_realm.cpp; path = Realm/ObjectStore/src/shared_realm.cpp; sourceTree = ""; }; - E32958826C878BB739499B7333715279 /* external_commit_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = external_commit_helper.cpp; path = Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp; sourceTree = ""; }; - E3C38B9CEA209FE6C7811DF0EC3A1BA1 /* RLMTokenModels.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMTokenModels.m; path = Realm/RLMTokenModels.m; sourceTree = ""; }; - E410D4DEBDC4874F18B3D7909C7A1696 /* ObjectSchema.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ObjectSchema.swift; path = RealmSwift/ObjectSchema.swift; sourceTree = ""; }; - E411A99878B86694C03B7A97DB39278F /* ReactiveSwift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = ReactiveSwift.modulemap; sourceTree = ""; }; - E48EF4343180C760186C4E41CAD7F000 /* RLMResults_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults_Private.h; path = include/RLMResults_Private.h; sourceTree = ""; }; - E4A483371BD64280D772DF8835B57A97 /* ThrowAssertion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThrowAssertion.swift; path = Sources/Nimble/Matchers/ThrowAssertion.swift; sourceTree = ""; }; - E558444A08D66A43ACA92FF003508D39 /* SatisfyAnyOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SatisfyAnyOf.swift; path = Sources/Nimble/Matchers/SatisfyAnyOf.swift; sourceTree = ""; }; - E568962EBFCCAF4358F8957D8821A82C /* UISlider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UISlider.swift; path = ReactiveCocoa/UIKit/iOS/UISlider.swift; sourceTree = ""; }; - E607BD729441875C853ABD98B412B2F7 /* FoundationExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FoundationExtensions.swift; path = Sources/FoundationExtensions.swift; sourceTree = ""; }; - E69C8B15E7E7EC1D9A652DAC2784B0BB /* AssertionRecorder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertionRecorder.swift; path = Sources/Nimble/Adapters/AssertionRecorder.swift; sourceTree = ""; }; - E6D9E3AF330175AA70AFDF06735E8B8D /* QCKDSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QCKDSL.h; path = Sources/QuickObjectiveC/DSL/QCKDSL.h; sourceTree = ""; }; - E72339A6F866D44B06A0DAABEBFC423F /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E76883DC82488E8B8F3B191B2FD4F472 /* librealm-ios.a */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = archive.ar; name = "librealm-ios.a"; path = "core/librealm-ios.a"; sourceTree = ""; }; - E791635096951BE0C0F2A896763547E6 /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = Sources/Error.swift; sourceTree = ""; }; - E797468E6591915891B2AC36BAB076C0 /* ObjC+RuntimeSubclassing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ObjC+RuntimeSubclassing.swift"; path = "ReactiveCocoa/ObjC+RuntimeSubclassing.swift"; sourceTree = ""; }; - E857B5F6FE5852F628633EEF148CF32D /* NMBStringify.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NMBStringify.m; path = Sources/NimbleObjectiveC/NMBStringify.m; sourceTree = ""; }; - E91434E0A117153C76C3A751B5F996DA /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-resources.sh"; sourceTree = ""; }; - E9720D39B736427B7A488A19D48B7481 /* Marshaling.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Marshaling.swift; path = Sources/Marshaling.swift; sourceTree = ""; }; - EACF671AF68F0FF123F51158EB8C2033 /* ObjC+Constants.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ObjC+Constants.swift"; path = "ReactiveCocoa/ObjC+Constants.swift"; sourceTree = ""; }; - EBF692D6358518BFD66A3A1AF49F829A /* SDWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = SDWebImageManager.m; path = SDWebImage/SDWebImageManager.m; sourceTree = ""; }; - EC01834CF2177AD8BDE489FD5511D73F /* UnmarshalUpdating.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UnmarshalUpdating.swift; path = Sources/UnmarshalUpdating.swift; sourceTree = ""; }; - ECEA795175788999B204BC44FBD48FE0 /* UIActivityIndicatorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIActivityIndicatorView.swift; path = ReactiveCocoa/UIKit/UIActivityIndicatorView.swift; sourceTree = ""; }; - EDA1F5A214BB23FB8B82D8EF6A22A092 /* BeCloseTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeCloseTo.swift; path = Sources/Nimble/Matchers/BeCloseTo.swift; sourceTree = ""; }; - EE533E56D05E33E7D5F5CC8B4806F3CF /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - EEDE876B3316432FB3B299AFCF04D14A /* RLMSyncConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncConfiguration.mm; path = Realm/RLMSyncConfiguration.mm; sourceTree = ""; }; - EF52EE8C39F2294F4B0E818DD7228A29 /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThanOrEqualTo.swift; path = Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift; sourceTree = ""; }; - F00AD52E5921222022AFA34B7A9381CF /* QuickConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickConfiguration.m; path = Sources/QuickObjectiveC/Configuration/QuickConfiguration.m; sourceTree = ""; }; - F0EEE9DA2500490F96A921B7CBEA5293 /* RLMCollection.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMCollection.mm; path = Realm/RLMCollection.mm; sourceTree = ""; }; - F10F672222BE731F7EBA1ED547D8457A /* RLMSyncUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncUtil.mm; path = Realm/RLMSyncUtil.mm; sourceTree = ""; }; - F2003DAC1567552EAFAC7EDB58AACEF0 /* Marshal.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Marshal.xcconfig; sourceTree = ""; }; - F24BFF19FF08365F5A7A2FB97216ACCF /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAnInstanceOf.swift; path = Sources/Nimble/Matchers/BeAnInstanceOf.swift; sourceTree = ""; }; - F27228CB12B965FDC0DD1256B8843676 /* RLMSyncPermissionChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncPermissionChange.h; path = include/RLMSyncPermissionChange.h; sourceTree = ""; }; - F29326791202F9E0471DC360A0117CBF /* RLMClassInfo.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMClassInfo.mm; path = Realm/RLMClassInfo.mm; sourceTree = ""; }; - F3799C1205E4466C237F4B2CCA1AF7CB /* mach_excServer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mach_excServer.h; path = Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h; sourceTree = ""; }; - F389872021366FA1398C0313163136D3 /* RealmSwift.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = RealmSwift.xcconfig; sourceTree = ""; }; - F415CC75AC70334E315CAA5786E84027 /* MatcherProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherProtocols.swift; path = Sources/Nimble/Matchers/MatcherProtocols.swift; sourceTree = ""; }; - F4166BF3271091D2B727C28AA3921B51 /* RaisesException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RaisesException.swift; path = Sources/Nimble/Matchers/RaisesException.swift; sourceTree = ""; }; - F41849D4EFEC7E703EE4C478513EEBE1 /* Nimble-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Nimble-umbrella.h"; sourceTree = ""; }; - F4494BF2ED5BE24DDD19C9DBA9830F21 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-frameworks.sh"; sourceTree = ""; }; - F487F50FEA89C151AF2484ECACBFDD60 /* SDWebImagePrefetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SDWebImagePrefetcher.h; path = SDWebImage/SDWebImagePrefetcher.h; sourceTree = ""; }; - F49316E992C1B0F07E808EDF3EC85A13 /* UIGestureRecognizer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIGestureRecognizer.swift; path = ReactiveCocoa/UIKit/UIGestureRecognizer.swift; sourceTree = ""; }; - F4E60902B8DF5048C387EC367747141F /* QuickSpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickSpec.h; path = Sources/QuickObjectiveC/QuickSpec.h; sourceTree = ""; }; - F5D657F808F31DBEC7DF6D04AE5FF7C0 /* Functional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Functional.swift; path = Sources/Nimble/Utils/Functional.swift; sourceTree = ""; }; - F5E84A9ECBA5E9CBA363FABBCB4BAE00 /* NSObject+Association.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSObject+Association.swift"; path = "ReactiveCocoa/NSObject+Association.swift"; sourceTree = ""; }; - F6471A97D6C579D396EA6FC04E28003A /* RealmCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RealmCollection.swift; path = RealmSwift/RealmCollection.swift; sourceTree = ""; }; - F737531120822D2EF585EEFF24764A32 /* Operators.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Operators.swift; path = Sources/Operators.swift; sourceTree = ""; }; - F779D8E6F5B54B674B2C1DE7147A2081 /* sync_manager.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_manager.cpp; path = Realm/ObjectStore/src/sync/sync_manager.cpp; sourceTree = ""; }; - F7905E8E9D37C85C9BD0EB303513B3E0 /* SignalProducer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SignalProducer.swift; path = Sources/SignalProducer.swift; sourceTree = ""; }; - F7D8A7566C6856373259F87570F1D754 /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Sources/Quick/DSL/DSL.swift; sourceTree = ""; }; - F8C8CFCE00F3EBFB11B577E7C8AFD9BA /* UIKitExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UIKitExtensions.swift; sourceTree = ""; }; - F98732B1434617349CC7A856209E7BD5 /* RealmExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RealmExtensions.swift; sourceTree = ""; }; - F9DADD469BEF86B09668FD34C201561A /* Realm-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Realm-prefix.pch"; sourceTree = ""; }; - F9DF474F5F5E99E4053356B4C5495B51 /* EndWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EndWith.swift; path = Sources/Nimble/Matchers/EndWith.swift; sourceTree = ""; }; - FAD121BAA02D2C889D46657A71F70ACE /* DSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DSL.m; path = Sources/NimbleObjectiveC/DSL.m; sourceTree = ""; }; - FB85B3D7A8C497D83BA5909F75169A46 /* list_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = list_notifier.cpp; path = Realm/ObjectStore/src/impl/list_notifier.cpp; sourceTree = ""; }; - FBEAFC9508E42802E0BBA63D0F16AC56 /* RealmSwift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RealmSwift-umbrella.h"; sourceTree = ""; }; - FDA069771BD828C2580F38C207E31D4D /* Runes.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Runes.framework; path = Runes.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - FDC1470EB12CB6AAD6CC04DF5CDF56D7 /* MarshalDictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MarshalDictionary.swift; path = Sources/MarshalDictionary.swift; sourceTree = ""; }; - FE34C1D3F9802D08338B451C4791163E /* ObjCRuntimeAliases.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ObjCRuntimeAliases.m; path = ReactiveCocoa/ObjCRuntimeAliases.m; sourceTree = ""; }; - FE8A03AFB4C021181EED12B188D46578 /* RealmSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - FEA8A273E8F0B9F8F7DF5BE1EF5F429E /* collection_notifications.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_notifications.cpp; path = Realm/ObjectStore/src/collection_notifications.cpp; sourceTree = ""; }; - FF8983CAC2414B821F670C16DF465A9C /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 09339920AAC2C898CF062C08E8504BDF /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 877D85263043DFE712C617A0C59365A7 /* Foundation.framework in Frameworks */, - C5DFC8128DE5000694C911873D37B444 /* Runes.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0C75D523EFEDDA8D8D1B3F80210DA1D1 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C232796CFD79FCCDAABF9B35E90C545B /* Argo.framework in Frameworks */, - 35CAAAB3D054631676638C0D526C364F /* Foundation.framework in Frameworks */, - F7F22DF927703C41524BF33CF14A45CF /* Marshal.framework in Frameworks */, - 3080659C90D5328E41FE5FF659F325A8 /* Reachability.framework in Frameworks */, - 469E2AD072EB9A7ED6E43929375E961B /* ReactiveCocoa.framework in Frameworks */, - AEA36D26E43E510E6CE8D61593C95A2A /* ReactiveSwift.framework in Frameworks */, - E5CB937578428DF7549E98D85827A430 /* Realm.framework in Frameworks */, - D9AFC3FCAC0A5683669C9096964D307F /* RealmSwift.framework in Frameworks */, - BCBC5102BF00569BE8309116B3B8BBAD /* Result.framework in Frameworks */, - EB220DD776AE8EACA1486B5F8622E7C6 /* Runes.framework in Frameworks */, - 9F70699ABA6AED4577F9C027EF572700 /* SDWebImage.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0F6BA1262E8C8EE1060A0970B4EDA970 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7BBB202F4A3A235566C2146CEE813C48 /* Foundation.framework in Frameworks */, - 72630AA3A5D8D8F5DA055ECC19B98B58 /* SystemConfiguration.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 34091F7A20179AF439E5793B51FCF406 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 08924C40CB922735E6F138F404DB8FB7 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 42FEE9C4C2A3C7EC571A1A1A3073BB7D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - AD8A2AE3E3391149462A67D784670F27 /* Foundation.framework in Frameworks */, - D022C285A2A086CB21E6B0049754FFDE /* ImageIO.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C16868C430A16DED48B21AEF479D04C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 719D27143139E827ED71B4EA147F1AEE /* Foundation.framework in Frameworks */, - 9E7A6B432FD9D03B8C2EC3180525177A /* XCTest.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5126F3ADB8F1EF2A4F09AC5235376EEE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - FBAD342C95EDAC2AD5EDA2486B61D8D1 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 62C3B53A7993272A742952C3F5E108BD /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 5A41AC00D39F27E8B0124ACAC8528442 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 69FCD5E0AABA3F8DBB1004DF32E31FF0 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 64A16CB7A74E20B810FE6D7879935961 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6BC1965B9C665C0703945A6BFA8DEEEA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - CE1D57D33061B0827F195EFE28B52397 /* Foundation.framework in Frameworks */, - A369B6AB9AB7A60CAFBB3169832D18F8 /* ReactiveSwift.framework in Frameworks */, - AA5C81AC887E7F2A0875948D3D3972B9 /* Result.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7AB9AD551FAE028D9517461DA1CEA573 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E992CC54CAA1360B9C2E528F9AB2BBAB /* Foundation.framework in Frameworks */, - 343FC11494AC031FD071A2B978881A02 /* Result.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - BB660921F4ADB723015A48AE39A34B4A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D3DF9582A32ACA322C7E53CF9F84F6AD /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DBE2CE2F5ED086FC1DD44D4B176AEA5B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 24EF979DB6A2B88464E07F5C5937EE14 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E1656C806D61CD0B3B68DBC573EB213D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1A99ECCFD665C81328E2C765A7853257 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E76ADB945D5AA52797580E298B9F1419 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 806B25F17A7AED6E1C53A7CD7B909B16 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - FA4B33CED0F7A897CFB617B0B45554E6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 42B8CC75C2318A9B48B66D996C478CAD /* Foundation.framework in Frameworks */, - 211BA0ADE37913AA85C1E5FD52370C64 /* Realm.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 00E0F19B3926EFDC3BED69C30970490C /* Pods */ = { - isa = PBXGroup; - children = ( - AA89DC7490103AC3F7DA4F2AAB08982C /* Argo */, - C6BEC40D6EC8DE20279DB15F6C775247 /* Curry */, - 794492E43F513722A0D62F682AA8E803 /* Marshal */, - 0C7E0CD31ECC59F6FBF81571EB890FAF /* Nimble */, - EDC3DDD530BD064532119AC6B440CF3F /* Quick */, - 5F27E733C63A6E68CC1A3F2AE4DCEC25 /* Reachability */, - 4BFA8C8925C3A8640EA6144C3992D78C /* ReactiveCocoa */, - 085AECBAFB395BF566E1E5128E43DFE2 /* ReactiveSwift */, - 62C4B899BDE9044A47726467D24DE2EE /* Realm */, - DF805A8806DEA6F681575D3CD2868705 /* RealmSwift */, - 4B0BF935205784DAD5FDC38C9CDA3307 /* Result */, - 2DD3687D95FB92F378C528856D315DE5 /* Runes */, - 0128731A4F4525DB77436AF33FCC7E06 /* SDWebImage */, - ); - name = Pods; - sourceTree = ""; - }; - 010BC59F19B541526323A272CF9E778B /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - E1778246C31EB0AB84E858C9CCB851FA /* Argo */, - 30E8B186067705C72D02C49C96304A97 /* Core */, - 1F515182DAC3BBC678A4E4CB82E42809 /* Marshal */, - D3ACF36CF58F495DE54D55DE45C35529 /* Reachability */, - C2739D02082121948CAA6AA694A7F02A /* Realm */, - 889293C48C50160D065C78A81D0006FA /* SDWebImage */, - 734C7F716B401211A0EFB418F4F86A4B /* Support Files */, - F77EC3F20FD4F8B8AC87D2FE69024E7C /* UIKit */, - E316614E71150DDA26F8A9A87961ED30 /* WebKit */, - ); - name = ACKReactiveExtensions; - path = ../..; - sourceTree = ""; - }; - 0128731A4F4525DB77436AF33FCC7E06 /* SDWebImage */ = { - isa = PBXGroup; - children = ( - 55BE8B433E758EE203C22C6A7A9E42A6 /* Core */, - 4448E7D3D9A260EAB6D78E11677E17E7 /* Support Files */, - ); - name = SDWebImage; - path = SDWebImage; - sourceTree = ""; - }; - 0635BF8AFF0B68C8DF92C8154980780F /* Headers */ = { - isa = PBXGroup; - children = ( - C83184A660ADDBE83E50CB93257B58CD /* Realm.h */, - 67DB0CBF7F97920F9ABEFC7BC7BE9DA3 /* RLMArray.h */, - 09EBF73F678AC49042C057CECA6D9C9B /* RLMCollection.h */, - 91BB85FE67400DD1B6A46E08596D0760 /* RLMConstants.h */, - DF14F4BCFCB54C50CC44B9F24A1C06E0 /* RLMMigration.h */, - 9397232493D47E251FCD38B034EF4755 /* RLMObject.h */, - AA9436789E37E80359F8A2176F388D3B /* RLMObjectBase.h */, - 13B9E00A2ADFC7E032F45885B40B5822 /* RLMObjectBase_Dynamic.h */, - 85FB91F281737568C40E1BE91EC624BE /* RLMObjectSchema.h */, - 966BAD0CEA9341185E138C46BDC13777 /* RLMPlatform.h */, - 7933A983C1B0B4BC46FB1FC2C3BDDD66 /* RLMProperty.h */, - 37F3E162DF05333F41599C41E7EA11AC /* RLMRealm.h */, - 6B4B4D235F8BAAE064E0DFCC37393113 /* RLMRealm_Dynamic.h */, - D2DBF88CB3F9FA28E0C8002374D860DA /* RLMRealmConfiguration.h */, - 83DA572BDB4AE6A871F42422970968DC /* RLMRealmConfiguration+Sync.h */, - 1EF18CB021556D923160AE960C55D41F /* RLMResults.h */, - 979DECF18FE73967EBA41B3938401CA8 /* RLMSchema.h */, - BDB9157B69478671E392C9CF309B1BBD /* RLMSyncConfiguration.h */, - AC9EF25517ED5300468609A48031872D /* RLMSyncCredentials.h */, - CFCCDC4D7CE01D0325D2BFC246BDD146 /* RLMSyncManager.h */, - F27228CB12B965FDC0DD1256B8843676 /* RLMSyncPermissionChange.h */, - 3738F2E81E3C0A011D2B72D4A74BF811 /* RLMSyncSession.h */, - B4DB6173F603EAE2C38283B1018FE1AD /* RLMSyncUser.h */, - 9DC1BCD07008B3D42C609AE5328DCB8C /* RLMSyncUtil.h */, - ); - name = Headers; - sourceTree = ""; - }; - 085AECBAFB395BF566E1E5128E43DFE2 /* ReactiveSwift */ = { - isa = PBXGroup; - children = ( - 1825C4323B1B212C8024BCD288E82126 /* Action.swift */, - BACBB011CA1C6A70A56074BE121474A3 /* Atomic.swift */, - DF2759610C450FD80023B3565046245D /* Bag.swift */, - E083C71019FF77A198A3A5B6729E9C16 /* Deprecations+Removals.swift */, - 8069B37F697707BB94630A7CFF7465E3 /* Disposable.swift */, - 6A1A26B81673A0FA39FB285C2142D4A8 /* Event.swift */, - 03F8C403E25985E9B3F49A7D80B55B8F /* EventLogger.swift */, - 660B1F6A04701B2F3FF99A48AAD00CDC /* Flatten.swift */, - E607BD729441875C853ABD98B412B2F7 /* FoundationExtensions.swift */, - 314B8B6D64D349093EF3480BEE71626D /* Lifetime.swift */, - 500126F1D939EB7923C0A0A4FE4E7119 /* Observer.swift */, - 6B0E4E4C02341EF78603E824B2733137 /* Optional.swift */, - 2700DED06348763C77CC011CE6DB3AB2 /* Property.swift */, - 35C829B3ED1CE47110FB4243A4AA1DD0 /* Reactive.swift */, - 3D5719DF5A213B3338485A997A32CD31 /* ResultExtensions.swift */, - 03AB32EFA3403D705D88D68795CBFACA /* Scheduler.swift */, - BF6AFC9457459627BE4924716346183F /* Signal.swift */, - F7905E8E9D37C85C9BD0EB303513B3E0 /* SignalProducer.swift */, - C5FCFC7C955830E67FEC0C8844B49590 /* TupleExtensions.swift */, - 7087BC923ECE8A70F3168A6EF38FE9E4 /* UnidirectionalBinding.swift */, - 2AAD639877DAE67319D9E59A0115D29F /* ValidatingProperty.swift */, - E80BDF0AF9838FB08A255170F967C489 /* Support Files */, - ); - name = ReactiveSwift; - path = ReactiveSwift; - sourceTree = ""; - }; - 0C7E0CD31ECC59F6FBF81571EB890FAF /* Nimble */ = { - isa = PBXGroup; - children = ( - 5956ED9D5D7E478706DC7E2A5E06C24B /* AdapterProtocols.swift */, - 0DABADFC45B8EE874A1A92B9AF644D9A /* AllPass.swift */, - 1DF3E05F9FFAE9E02C11FE84296F7A20 /* AssertionDispatcher.swift */, - E69C8B15E7E7EC1D9A652DAC2784B0BB /* AssertionRecorder.swift */, - AF28C6F7F43248012239061C17517C4F /* Async.swift */, - 7105FDADD9F5EA077FCF4AB41527F29A /* AsyncMatcherWrapper.swift */, - 6F298A6855749549EF58B48DBA763B3F /* BeAKindOf.swift */, - F24BFF19FF08365F5A7A2FB97216ACCF /* BeAnInstanceOf.swift */, - EDA1F5A214BB23FB8B82D8EF6A22A092 /* BeCloseTo.swift */, - 78D56E6C8D49BE35A469566AD3FB1761 /* BeEmpty.swift */, - 6215008A04F973F0AE63DD326BD1C487 /* BeginWith.swift */, - A21F857CC9433B920B0AB4D045D27935 /* BeGreaterThan.swift */, - EF52EE8C39F2294F4B0E818DD7228A29 /* BeGreaterThanOrEqualTo.swift */, - 2C0202A6056A7E85A9737903599CC8EA /* BeIdenticalTo.swift */, - CF5A0E74BE0C0E430EE089E1795F92EC /* BeLessThan.swift */, - 89F1EE46FE6D88D9792F383AF2EE5E79 /* BeLessThanOrEqual.swift */, - E1496F2101AA68CBAF4B9E8ECBA7FBC6 /* BeLogical.swift */, - A5B16B462FDEFE1759C0D8EAE416E19E /* BeNil.swift */, - 39424FC5D2544CC107EC61D28A83CF56 /* BeVoid.swift */, - 54DA9444F1ED16C10D04D55654096038 /* Contain.swift */, - B2E943780D14D82033A5A724B6B18E47 /* CurrentTestCaseTracker.h */, - 583DFEF3167808DBE921F927EC0647D5 /* CwlBadInstructionException.swift */, - 5B1AC27116D413175DD38E2EDF04552C /* CwlCatchBadInstruction.h */, - 83A979E39ECA440AAF10D35FD95D0108 /* CwlCatchBadInstruction.m */, - 8A4BD9BF1A83C0E6C3FABF55C75DC471 /* CwlCatchBadInstruction.swift */, - 1E033FD8AF63521D07649FF36BA00D05 /* CwlCatchException.h */, - 597631411F419DF710CD14B247BB2214 /* CwlCatchException.m */, - 0164F42CC6FE0DCACF764700A6AA70EE /* CwlCatchException.swift */, - 2D5876B32CC2BEF0944820D2E3E548C6 /* CwlDarwinDefinitions.swift */, - CCD6D21B1824B199A28FD405F7F080B9 /* DSL.h */, - FAD121BAA02D2C889D46657A71F70ACE /* DSL.m */, - 5E0BBF837B9CC5EDE662153D4FED782F /* DSL.swift */, - BD8908482E11690C4B6D21DFDDF4B4A9 /* DSL+Wait.swift */, - F9DF474F5F5E99E4053356B4C5495B51 /* EndWith.swift */, - 44635410948DB4459D0131ECF77E61BA /* Equal.swift */, - D0FBA9589FAAE69C553734B593FEB496 /* Errors.swift */, - 15D83EDBD81AAA3246E77DEF3354B760 /* Expectation.swift */, - CEEE75D737864E8B717EE9DAC08740CF /* Expression.swift */, - 69521AAD7D6505125DEA62C9B1AC7B2A /* FailureMessage.swift */, - F5D657F808F31DBEC7DF6D04AE5FF7C0 /* Functional.swift */, - 2FFEB587006CF17159C316E5FEEF46D5 /* HaveCount.swift */, - 9303ABBB4DD1AC4EFC6B839FB06EA148 /* mach_excServer.c */, - F3799C1205E4466C237F4B2CCA1AF7CB /* mach_excServer.h */, - 7008F7E5A7BC03218B8379B5924B5CAB /* Match.swift */, - 271B749B3794F95755E02521F7C6895C /* MatcherFunc.swift */, - F415CC75AC70334E315CAA5786E84027 /* MatcherProtocols.swift */, - 6C206A1AEEA9ABF086EFA4DB5A915A02 /* MatchError.swift */, - 05310AA14FB2E89FACDD353E85A90C83 /* Nimble.h */, - 6B2E01CA5514B90525ECF3E081451287 /* NimbleEnvironment.swift */, - 0ADA808F7F6AD97110E89F0B217B8654 /* NimbleXCTestHandler.swift */, - 6EE4CFE17744FA0B4EE48863BB8E6C0C /* NMBExceptionCapture.h */, - 36CF93C5412F9C4395C0E134F672EE31 /* NMBExceptionCapture.m */, - 0E46BEDB9FE2948BDB0C0A8EC1E43306 /* NMBExpectation.swift */, - 7CDC63EAB2558BED1B47A3463C271EF3 /* NMBObjCMatcher.swift */, - C5AD5CA181843E2D59C76185F9F9166A /* NMBStringify.h */, - E857B5F6FE5852F628633EEF148CF32D /* NMBStringify.m */, - CF327CD37DCDC6B4C4D9F34962D9CEC5 /* PostNotification.swift */, - F4166BF3271091D2B727C28AA3921B51 /* RaisesException.swift */, - E558444A08D66A43ACA92FF003508D39 /* SatisfyAnyOf.swift */, - 7097638BF5C5369199675574769441C3 /* SourceLocation.swift */, - 037388FFAA7D6DD4BCFB36762737DC94 /* Stringers.swift */, - E4A483371BD64280D772DF8835B57A97 /* ThrowAssertion.swift */, - 7EA57594A19435F5B4B1409AB307B27A /* ThrowError.swift */, - A00AAA4C6E10464A3405F98A180C3FB0 /* XCTestObservationCenter+Register.m */, - 8F33BE6EC19A8BB90C752772B082535E /* Support Files */, - ); - name = Nimble; - path = Nimble; - sourceTree = ""; - }; - 1F515182DAC3BBC678A4E4CB82E42809 /* Marshal */ = { - isa = PBXGroup; - children = ( - F4635CB361557CC524C17ECE05A34FE9 /* ACKReactiveExtensions */, - ); - name = Marshal; - sourceTree = ""; - }; - 1F748482AFC3D42BAC405DC5556ECADE /* UIKit */ = { - isa = PBXGroup; - children = ( - 9447ABB644366BA6F61BEF379830782A /* Deprecations.swift */, - F8C8CFCE00F3EBFB11B577E7C8AFD9BA /* UIKitExtensions.swift */, - ); - name = UIKit; - path = UIKit; - sourceTree = ""; - }; - 214834FA74D5096C95CDEE9216B6DCE6 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E76883DC82488E8B8F3B191B2FD4F472 /* librealm-ios.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 25DB1B10714008D7B2A9D635B31BA2D0 /* Pods-ACKReactiveExtensions_Example */ = { - isa = PBXGroup; - children = ( - B7807DA6E11433098395A6E72530968A /* Info.plist */, - CB3B717D0FF7591F99AE31AA779EE817 /* Pods-ACKReactiveExtensions_Example.modulemap */, - A04C8302566928C5C225A03FAF0C7875 /* Pods-ACKReactiveExtensions_Example-acknowledgements.markdown */, - AC757E793AB194E266338F08E1E2C0F4 /* Pods-ACKReactiveExtensions_Example-acknowledgements.plist */, - 8E38F0DF683B927E30C0D6581557086D /* Pods-ACKReactiveExtensions_Example-dummy.m */, - 2AF55CC1A2AD69D3B329C324E8B20679 /* Pods-ACKReactiveExtensions_Example-frameworks.sh */, - 8F676FA1A07445F3F1211E9D7D5FF126 /* Pods-ACKReactiveExtensions_Example-resources.sh */, - 712808AA58D0CF2BE85538F15BA355BB /* Pods-ACKReactiveExtensions_Example-umbrella.h */, - B99B990B81693D607321364CAD6D517D /* Pods-ACKReactiveExtensions_Example.debug.xcconfig */, - 2718B96AF1AF5798736F5F61B15D2262 /* Pods-ACKReactiveExtensions_Example.release.xcconfig */, - ); - name = "Pods-ACKReactiveExtensions_Example"; - path = "Target Support Files/Pods-ACKReactiveExtensions_Example"; - sourceTree = ""; - }; - 27B5EE3DAD19C6CB453996007A9B3066 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 6E3212C0D35200745939E9D06B126836 /* WebKit */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - 2A00E2B5FC3F0F18960B3804A8A75EAF /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests */ = { - isa = PBXGroup; - children = ( - FF8983CAC2414B821F670C16DF465A9C /* Info.plist */, - A5A9D071939A19BBD61396BB404F35FF /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.modulemap */, - 06D29CE181107BC1B82D7636DB86EA74 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.markdown */, - AC25F299AE01ECBE0FA85A2645691649 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-acknowledgements.plist */, - AE0F8E56CD72C260B37D78AB6061F35F /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m */, - F4494BF2ED5BE24DDD19C9DBA9830F21 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-frameworks.sh */, - E91434E0A117153C76C3A751B5F996DA /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-resources.sh */, - D10832EF3E35D8B927A00C7D9AD97AC7 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h */, - 3CA2661FAA5D698D8172B937E805E9D0 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.debug.xcconfig */, - CCC0CA1E4D7FCB37BB43C06596770A3C /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.release.xcconfig */, - ); - name = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests"; - path = "Target Support Files/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests"; - sourceTree = ""; - }; - 2C15E69E9D1FB27F573295452DCB4951 /* Support Files */ = { - isa = PBXGroup; - children = ( - 7926680981FA4A7419448AD54A1843F8 /* Curry.modulemap */, - 8B7379B6BEAA2C66A9A218110F722599 /* Curry.xcconfig */, - B4F914D5FC0B1958CA70FE28F125D23A /* Curry-dummy.m */, - 5632D95E55EEE3F8E42F36694AA3C8F6 /* Curry-prefix.pch */, - 7CB9A2CC4443A5D98CC7C8883879D405 /* Curry-umbrella.h */, - 6ADBEE110332037CCF4855CB62C96890 /* Info.plist */, - ); - name = "Support Files"; - path = "../Target Support Files/Curry"; - sourceTree = ""; - }; - 2DD3687D95FB92F378C528856D315DE5 /* Runes */ = { - isa = PBXGroup; - children = ( - A8907DBAC4A353CD157422CC1361BE27 /* Array.swift */, - A0F59BF4AD6298FBBDEF7F8FFC6E2DFC /* Optional.swift */, - CE589D63713D983B7A2CC10D113B938D /* Runes.swift */, - ACBE54D9C6D8F699BE557F2402DF76CA /* Support Files */, - ); - name = Runes; - path = Runes; - sourceTree = ""; - }; - 30E8B186067705C72D02C49C96304A97 /* Core */ = { - isa = PBXGroup; - children = ( - F3096812C6F2877DE030EB1486AD7B87 /* ACKReactiveExtensions */, - ); - name = Core; - sourceTree = ""; - }; - 36EEC49BD4B46D32A0800F1A65203560 /* Marshal */ = { - isa = PBXGroup; - children = ( - A516F7D84ED85B2E9DECFBB69017DDD1 /* MarshalMapping.swift */, - ); - name = Marshal; - path = Marshal; - sourceTree = ""; - }; - 4114B6AACBA0B9E7132902C436403BEC /* Support Files */ = { - isa = PBXGroup; - children = ( - B8F5CA7E198B6B863E097683798AE42A /* Info.plist */, - 5A8C6A2BCD4DC200FF37D71F8703A4BC /* Marshal.modulemap */, - F2003DAC1567552EAFAC7EDB58AACEF0 /* Marshal.xcconfig */, - 49D6560115C7B2BC53A70882B073C3B1 /* Marshal-dummy.m */, - 79BA6850B472A54BE2BA2ACA3DD0D230 /* Marshal-prefix.pch */, - 0EF7846F5E3452A9E25F6256E9C1ADB8 /* Marshal-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Marshal"; - sourceTree = ""; - }; - 4239C08209C911B11BCDB9DDD4CF6AF3 /* SDWebImage */ = { - isa = PBXGroup; - children = ( - 4006BC04F14AE7E96891627AAA66B46A /* SDWebImage+RAC.swift */, - ); - name = SDWebImage; - path = SDWebImage; - sourceTree = ""; - }; - 4448E7D3D9A260EAB6D78E11677E17E7 /* Support Files */ = { - isa = PBXGroup; - children = ( - 5AF744E9747D20F1326DA20382BB8FE4 /* Info.plist */, - 67ED53E6A7BAEC9E2A57E18D07095477 /* SDWebImage.modulemap */, - 33BC9D10BB8C5D4C51A61305E606E8E4 /* SDWebImage.xcconfig */, - 12254A6FC014605B8F73CD71E05E2820 /* SDWebImage-dummy.m */, - 2B50E6355DCACE9410E347C3F5E5FB7A /* SDWebImage-prefix.pch */, - D636D627BCC9BA5B12D79DD65E7E7E63 /* SDWebImage-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/SDWebImage"; - sourceTree = ""; - }; - 490D1C736E1D9440A38E7162E61B6A1E /* Support Files */ = { - isa = PBXGroup; - children = ( - DAB72ED5D33B92009EA6EDCD838AA5DC /* Info.plist */, - 161E419EDCBFDC6BB9FDBE5B1D181DD2 /* RealmSwift.modulemap */, - F389872021366FA1398C0313163136D3 /* RealmSwift.xcconfig */, - 12612EF0C0D0DB42DA16F98083C20B82 /* RealmSwift-dummy.m */, - 60137E489216AC88928F589F37AC26EF /* RealmSwift-prefix.pch */, - FBEAFC9508E42802E0BBA63D0F16AC56 /* RealmSwift-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/RealmSwift"; - sourceTree = ""; - }; - 4B0BF935205784DAD5FDC38C9CDA3307 /* Result */ = { - isa = PBXGroup; - children = ( - 33EA03A6970E732035AFB8C2C7200168 /* Result.swift */, - C1215503EE4CF7889907BA3EF98947F5 /* ResultProtocol.swift */, - C7C4EDF24350E0A368D4ED3EE796ECFC /* Support Files */, - ); - name = Result; - path = Result; - sourceTree = ""; - }; - 4BFA8C8925C3A8640EA6144C3992D78C /* ReactiveCocoa */ = { - isa = PBXGroup; - children = ( - C72897D5228D7E9D0CA2BCF625481E0D /* CocoaAction.swift */, - 718DF05EBBCB9BDE444E6A5537C11253 /* CocoaTarget.swift */, - BA20BBD149564311AB716616EA39EEA6 /* DelegateProxy.swift */, - 21E816A500F1336215A73436B16258F1 /* Deprecations+Removals.swift */, - D42C961D3D18E87840C227EBD1663227 /* DynamicProperty.swift */, - 38CF7AFDBE6488050A4824C4E23C0777 /* MKMapView.swift */, - 7A4E14923BB45C7CE2295CAD3C4D2A0A /* NSLayoutConstraint.swift */, - F5E84A9ECBA5E9CBA363FABBCB4BAE00 /* NSObject+Association.swift */, - 5030F477E12364AAE5532F5BE20AE54E /* NSObject+BindingTarget.swift */, - B677F06DEB90ACF09C4C2C2E387E24A1 /* NSObject+Intercepting.swift */, - 232FC4E435DA00B8472D3DBBB13915A8 /* NSObject+KeyValueObserving.swift */, - 105FBA0BD89AFC25198AE4334E657AB6 /* NSObject+Lifetime.swift */, - 542C83EC4E362B1E4036EDB131C4B2CE /* NSObject+ObjCRuntime.swift */, - AC256ADDA6D2D62C6DD213773A7D60BE /* NSObject+ReactiveExtensionsProvider.swift */, - C4817823CC44D88678A94F02F15DE1CC /* NSObject+Synchronizing.swift */, - EACF671AF68F0FF123F51158EB8C2033 /* ObjC+Constants.swift */, - 04FFAB12851B9DEC440905468EFB3DF8 /* ObjC+Messages.swift */, - 0ED9810E50E8D4C73D14E85A64344E59 /* ObjC+Runtime.swift */, - E797468E6591915891B2AC36BAB076C0 /* ObjC+RuntimeSubclassing.swift */, - 4315946D5C791A0D917C598507FA8253 /* ObjC+Selector.swift */, - 4DD8D6C38CF84B39C4CD925866FE29A2 /* ObjCRuntimeAliases.h */, - FE34C1D3F9802D08338B451C4791163E /* ObjCRuntimeAliases.m */, - 9E16D1C7108C92F7132BFE96188F7AD2 /* ReactiveCocoa.h */, - 788E044960791E209D43E3E6104BA2CC /* ReusableComponents.swift */, - ECEA795175788999B204BC44FBD48FE0 /* UIActivityIndicatorView.swift */, - 0412A85F1E6549BEDB139D20B1ED081B /* UIBarButtonItem.swift */, - D76B8505276FA8CA680C74C2BF1FE31C /* UIBarItem.swift */, - 915E2130F82FBCD696E7B41FD2255114 /* UIButton.swift */, - C8F52136FC50F5C79B01F64DDC695D94 /* UICollectionView.swift */, - 96A1D01AD61167F40E747F4BA875E5B4 /* UIControl.swift */, - 1B3AA4360B79AA046AAE078E12F3DFFC /* UIDatePicker.swift */, - F49316E992C1B0F07E808EDF3EC85A13 /* UIGestureRecognizer.swift */, - D86207497AC6CFA632EC64CB15A5923F /* UIImageView.swift */, - D0F5AA65BC44CDE9194A8836CB27C67B /* UIKeyboard.swift */, - 2D3882CC443D7C99789F1CE6D7CA7975 /* UILabel.swift */, - D25DB37DEC6459819431654AECC624A6 /* UIPickerView.swift */, - 1AA0A291C2F56AA20159C8593C7CDF27 /* UIProgressView.swift */, - 512B9A5158A40CEC213006BE06F53315 /* UIRefreshControl.swift */, - 7222A864F00CCFD6624F1E635745EF2F /* UIScrollView.swift */, - 9441F22F2A6487F20303AD5F44F9AD34 /* UISearchBar.swift */, - 7B82C0D57E8ED3BBF27CBF4EF355DA41 /* UISegmentedControl.swift */, - E568962EBFCCAF4358F8957D8821A82C /* UISlider.swift */, - 09D5E0D36BF6CBA6279636E425EA8DD3 /* UIStepper.swift */, - 19ECB52F60624E4635D8091C15D6B9E1 /* UISwitch.swift */, - 7AAE65A0CE34A217C207333F15D71AB4 /* UITableView.swift */, - 334F857F93FC618C80B8306EA8C02F03 /* UITextField.swift */, - B4F88E0FF65CF094BD268C7C6D05A892 /* UITextView.swift */, - DCD5EBA74745951058FAC1CA3A947A45 /* UIView.swift */, - CF08B98229CE45F81470439F806118CC /* Support Files */, - ); - name = ReactiveCocoa; - path = ReactiveCocoa; - sourceTree = ""; - }; - 51A4870BCEAA63E5B4602B4F097A8DC8 /* Development Pods */ = { - isa = PBXGroup; - children = ( - 010BC59F19B541526323A272CF9E778B /* ACKReactiveExtensions */, - ); - name = "Development Pods"; - sourceTree = ""; - }; - 5561D711D409DF4B37326243DD61F26A /* Support Files */ = { - isa = PBXGroup; - children = ( - 3353ACBAA48DE70FC416B1908522FC87 /* Info.plist */, - 7B5DD5F72AFCC0E16F032E9427520111 /* Reachability.modulemap */, - 8BAEF129B05502833A3C38D1187D1F7B /* Reachability.xcconfig */, - B736AFE30B4A49758F137F1A60E57887 /* Reachability-dummy.m */, - 0B4E3DDA1CC29A78E565F115A8A00DD8 /* Reachability-prefix.pch */, - 3C92847251E673E2C9A4421274F02A9C /* Reachability-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Reachability"; - sourceTree = ""; - }; - 55BE8B433E758EE203C22C6A7A9E42A6 /* Core */ = { - isa = PBXGroup; - children = ( - 5307203EC65D843D6218225D81406D62 /* NSData+ImageContentType.h */, - 678DB41814A5FDAC91F12190877D99F4 /* NSData+ImageContentType.m */, - CF292D056F5D302553FC320659C05291 /* NSImage+WebCache.h */, - 1E7DA7E139F874EC8DF9C7A6D1E80337 /* NSImage+WebCache.m */, - 89BE574C4E94967835529C99140316AE /* SDImageCache.h */, - 1A4313403997D85BB033DC3CE9FE2DC9 /* SDImageCache.m */, - D2ACC5157986C4C2A2BDDEE70753BE4B /* SDImageCacheConfig.h */, - 3282A40C35AC3A6009A27E7C2E672D10 /* SDImageCacheConfig.m */, - D06DCE506336E68E74741682FA232A62 /* SDWebImageCompat.h */, - 126814190611329563A399525B529E45 /* SDWebImageCompat.m */, - 107AA785555CE6CCC4A8F3E2890C4499 /* SDWebImageDecoder.h */, - 50D246C696E1D1DDD1F8545492DE9F95 /* SDWebImageDecoder.m */, - 6508E193CF684DA6CB3E037900D61985 /* SDWebImageDownloader.h */, - 5573F218EC3FDDACDF98B941DAB1A9CE /* SDWebImageDownloader.m */, - 6BD95C70957EA9EA4B65B2D724C34C0E /* SDWebImageDownloaderOperation.h */, - 585421F892EECE0D46E02A75FADF3D32 /* SDWebImageDownloaderOperation.m */, - 1BBB569FFF4629F64B98D1DE16E37BE9 /* SDWebImageManager.h */, - EBF692D6358518BFD66A3A1AF49F829A /* SDWebImageManager.m */, - AACEA0B58AD6F1E95023ABD1DB5262F2 /* SDWebImageOperation.h */, - F487F50FEA89C151AF2484ECACBFDD60 /* SDWebImagePrefetcher.h */, - DDDFBDC4BDF1483CA04B98A0A2778B67 /* SDWebImagePrefetcher.m */, - BFBCA3AA47952AF10E6F190ED5CDE623 /* UIButton+WebCache.h */, - 1C64BBAFB45039E89DFE105FF7DD48E4 /* UIButton+WebCache.m */, - 55EF9D5B346E69E9CFF60DDC13761112 /* UIImage+GIF.h */, - C4F93A29DAA06C2D060AB252DB6933C6 /* UIImage+GIF.m */, - 2225060BAB6998F7631BB9AE0B59981B /* UIImage+MultiFormat.h */, - AE079783607F84C877F15ED9EB6260EF /* UIImage+MultiFormat.m */, - 3A6F6A940D43A1D2FB5248808880F468 /* UIImageView+HighlightedWebCache.h */, - DB2110822BD1008D595EA83C92482309 /* UIImageView+HighlightedWebCache.m */, - 1ADBD21F01F274E89DC35F39684A72FD /* UIImageView+WebCache.h */, - C473DA61E0BF8FC1FA2051931C41EDDE /* UIImageView+WebCache.m */, - A347A88FAFBC3EF3A8473E08354ADC1E /* UIView+WebCache.h */, - CA1B02C1EEE359F771F58A0FEE948908 /* UIView+WebCache.m */, - A6343B009137DD1A99C70E4FEDC837E3 /* UIView+WebCacheOperation.h */, - 0022F7705FB317525EB64D8310D6EA4E /* UIView+WebCacheOperation.m */, - ); - name = Core; - sourceTree = ""; - }; - 5F27E733C63A6E68CC1A3F2AE4DCEC25 /* Reachability */ = { - isa = PBXGroup; - children = ( - 7AD26234BEAE0119C20BE4064E6D1967 /* Reachability.h */, - 7491821E2D46EE33A835436948D1D049 /* Reachability.m */, - 5561D711D409DF4B37326243DD61F26A /* Support Files */, - ); - name = Reachability; - path = Reachability; - sourceTree = ""; - }; - 62C4B899BDE9044A47726467D24DE2EE /* Realm */ = { - isa = PBXGroup; - children = ( - 4F78E60DAA32E09751420F5C65B9F77D /* collection_change_builder.cpp */, - FEA8A273E8F0B9F8F7DF5BE1EF5F429E /* collection_notifications.cpp */, - BE07F2CED458B99C1A99A2A00AADF567 /* collection_notifier.cpp */, - E32958826C878BB739499B7333715279 /* external_commit_helper.cpp */, - 319D47A4E04B1D1850D15617B34731FE /* format.cpp */, - E01544D39F7477EE1534CC9385D68AC6 /* handover.cpp */, - 59733EB1ABE53D9A3DFD27170F416260 /* index_set.cpp */, - 6A33FB7ED3C98C702DBA6A53A8A1D633 /* keychain_helper.cpp */, - D2F719B9B7093A7E3611B4CBA6D4BD44 /* list.cpp */, - FB85B3D7A8C497D83BA5909F75169A46 /* list_notifier.cpp */, - 3F8D78E35B6799FBE72ED77EF444B26F /* object_schema.cpp */, - C5062007710E1BEE91B95001D87473D2 /* object_store.cpp */, - 5953293A5C09A44DF3E762819A0D6161 /* placeholder.cpp */, - 97500615959F3658229E0B487EA37835 /* realm_coordinator.cpp */, - 52653314A619A2302BEDBD734F4F9F36 /* results.cpp */, - 8004AF76C027BB4EBA37A5052DA1477C /* results_notifier.cpp */, - A901B8CEB82AF015D61F999D5A7E8D71 /* RLMAccessor.h */, - 0A006DAB665D087A81363738F07BB8F8 /* RLMAccessor.mm */, - 8E8CE214B1B86DA92092AE2CAA9E7725 /* RLMAnalytics.mm */, - 3BE1B17FB3D1786D4AE6C6793272FD66 /* RLMArray.mm */, - 0E1CDE383243D554B0D7CDF7F0A56864 /* RLMArray_Private.h */, - 0894A8ECFDE6892A88F6E589924D3B30 /* RLMArrayLinkView.mm */, - 5BAFEAED1D1237AB634CF4E6CFF8CAE7 /* RLMAuthResponseModel.m */, - F29326791202F9E0471DC360A0117CBF /* RLMClassInfo.mm */, - F0EEE9DA2500490F96A921B7CBEA5293 /* RLMCollection.mm */, - CAD193490FD0DBB2F2D5487F16FECFCE /* RLMConstants.m */, - A6D3216BE419DC5864B02E6F2201C034 /* RLMListBase.h */, - 02C9F75B74BA0614F8A1E06E422F7303 /* RLMListBase.mm */, - 59AC20E6AC41358A4AE618014B5DE572 /* RLMMigration.mm */, - B9C086F9429415130B95A4D9BD539C4A /* RLMMigration_Private.h */, - CC5BAA85DDD9939DB814BBEB2EEA6B00 /* RLMNetworkClient.m */, - 3C60070B0166160719DDB8E19B9F5462 /* RLMObject.mm */, - D48FF7D6643A2CA2A68C1C44D2E1C5C8 /* RLMObject_Private.h */, - 588716E07AB61E12616DE68E22140115 /* RLMObjectBase.mm */, - 839C4A8D444DC868D4C610DE4723D033 /* RLMObjectSchema.mm */, - C4A7A857A352C067C32F07E9DED5F857 /* RLMObjectSchema_Private.h */, - 31EA30FAB5AC797914D7B7A65FDF520D /* RLMObjectStore.h */, - 1650DFF9CACF5854F584E793258BA15C /* RLMObjectStore.mm */, - 64BA96A52A8B3B259F42459013F60BE8 /* RLMObservation.mm */, - 60A002572AC20E5406A90AAC57DFF042 /* RLMOptionalBase.h */, - AEDF0E9F5960B84839C674C69004405F /* RLMOptionalBase.mm */, - B382581DC6AB3FAD73955AE651D3AB2A /* RLMPredicateUtil.mm */, - 2A1F6288289D29790139F1B3F4860185 /* RLMProperty.mm */, - 4AC6B8BF65E2C5C0DB2344F42211B2AE /* RLMProperty_Private.h */, - A7DDC7C79747E06F695CFE767BF514FC /* RLMQueryUtil.mm */, - CFBF2C669407931F2E961AB92AEA7F1D /* RLMRealm.mm */, - 9F4C34DBECC5FC8CDC1A5D97DFC0095A /* RLMRealm_Private.h */, - 1FC4B0E456455B6FA693C53B90618F36 /* RLMRealmConfiguration.mm */, - AF4D7C33BF3FCD7F5980750DFE079618 /* RLMRealmConfiguration+Sync.mm */, - C09657AF9A1B91C4D3AEDB678B9BEAD0 /* RLMRealmConfiguration_Private.h */, - 469F6A5444E5788B3E182DD479E78253 /* RLMRealmUtil.mm */, - 0D0F4809D8692C621FA463BF89809892 /* RLMResults.mm */, - E48EF4343180C760186C4E41CAD7F000 /* RLMResults_Private.h */, - 0196CF826E8303E0BAB94B7B6EA71FDB /* RLMSchema.mm */, - 33FD8512741E03356DC3075014CB736C /* RLMSchema_Private.h */, - D7ADF689A2FEBF5D2B0B97224BE6E39A /* RLMSwiftSupport.m */, - EEDE876B3316432FB3B299AFCF04D14A /* RLMSyncConfiguration.mm */, - C2123A0484B67CA9CC476814C0120E75 /* RLMSyncConfiguration_Private.h */, - DAD9C8DAF1108DFF164034DBD5137A01 /* RLMSyncCredentials.m */, - 64D4DAB0875793978F8CC3CBFADBCC0D /* RLMSyncErrorResponseModel.m */, - 3E756BFADC9AAFF0AE85096AE9A526B5 /* RLMSyncManager.mm */, - 60E31CE3FBB85A560035ACF301565420 /* RLMSyncManager_Private.h */, - CDE76D1DE6FC0A51387FEF2D10B199EC /* RLMSyncPermissionChange.m */, - 9219C02824374A414928D9E2AC846ACF /* RLMSyncPermissionChange_Private.h */, - 82D2257099413C297FBE7E94B01F5DEA /* RLMSyncSession.mm */, - C965627E2D5F1E9A4CF94AD8CEC1A480 /* RLMSyncSessionRefreshHandle.mm */, - 01D68A2A4CAE81125EC2676085493945 /* RLMSyncUser.mm */, - F10F672222BE731F7EBA1ED547D8457A /* RLMSyncUtil.mm */, - 0ADA20B5CF9E864675679D4999BF006D /* RLMSyncUtil_Private.h */, - E3C38B9CEA209FE6C7811DF0EC3A1BA1 /* RLMTokenModels.m */, - 564DF2424B8E212FED546E5CF3D4DEC9 /* RLMUpdateChecker.mm */, - 1AB2EFDA17A907E630213AEDF7F8A7C1 /* RLMUtil.mm */, - B4B1E8C437B59066AD9B23630A086B09 /* schema.cpp */, - E2150184B2621EB4006941B2B9094AB1 /* shared_realm.cpp */, - 285950CBD7CBC55792C73CA9492F7EA7 /* sync_file.cpp */, - F779D8E6F5B54B674B2C1DE7147A2081 /* sync_manager.cpp */, - 803396491622E4B64777359DFE9C44FB /* sync_metadata.cpp */, - A01AEAB1941A302C8B6218CE188443B0 /* sync_session.cpp */, - DE26BE6B3B2A24098629C1CDA4775E7C /* sync_user.cpp */, - 03C9AF42C06446ECC6AAFF6D6802866D /* thread_confined.cpp */, - 53096508F660433426E57D71FA76C816 /* transact_log_handler.cpp */, - 059A2B4445E82FAF328D7F61095B3AFB /* weak_realm_notifier.cpp */, - 214834FA74D5096C95CDEE9216B6DCE6 /* Frameworks */, - 0635BF8AFF0B68C8DF92C8154980780F /* Headers */, - 8AD09635FAC1A0358319803A035A959B /* Support Files */, - ); - name = Realm; - path = Realm; - sourceTree = ""; - }; - 6E3212C0D35200745939E9D06B126836 /* WebKit */ = { - isa = PBXGroup; - children = ( - 68CFF6EA076886323E883D239FC2D72F /* WebKitExtensions.swift */, - ); - name = WebKit; - path = WebKit; - sourceTree = ""; - }; - 6EE1CCCE48AD9922DBFC8E69F35BCC31 /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - 25DB1B10714008D7B2A9D635B31BA2D0 /* Pods-ACKReactiveExtensions_Example */, - 2A00E2B5FC3F0F18960B3804A8A75EAF /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - 734C7F716B401211A0EFB418F4F86A4B /* Support Files */ = { - isa = PBXGroup; - children = ( - 1088B70537CAD4A6E970D588E739FA4B /* ACKReactiveExtensions.modulemap */, - A8FE40626F29606EE28AF5449B7B14CD /* ACKReactiveExtensions.xcconfig */, - 991B28D558F7F4AB0752F5EDF23FEE75 /* ACKReactiveExtensions-dummy.m */, - B3E17E98C83930E4548DECCCCE0E0F48 /* ACKReactiveExtensions-prefix.pch */, - C2CB229C70353D865CBCDCD994B056AA /* ACKReactiveExtensions-umbrella.h */, - EE533E56D05E33E7D5F5CC8B4806F3CF /* Info.plist */, - ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/ACKReactiveExtensions"; - sourceTree = ""; - }; - 794492E43F513722A0D62F682AA8E803 /* Marshal */ = { - isa = PBXGroup; - children = ( - E791635096951BE0C0F2A896763547E6 /* Error.swift */, - 0DD64BEE47F7F882E962E75DEB7F825F /* JSON.swift */, - E1ABBE197ADEF9C7B459DCBAA0430C87 /* KeyType.swift */, - FDC1470EB12CB6AAD6CC04DF5CDF56D7 /* MarshalDictionary.swift */, - C63A2CD4F2A7F04523574F9DD1199A3C /* MarshaledObject.swift */, - E9720D39B736427B7A488A19D48B7481 /* Marshaling.swift */, - 7E0C2146E06F8FE932AAC749F843932D /* Migration.swift */, - F737531120822D2EF585EEFF24764A32 /* Operators.swift */, - 9329FB7EF8E0C35A84BFAB0448E91888 /* Unmarshaling.swift */, - 392220F412D83DABB8377C6A3546887B /* UnmarshalingWithContext.swift */, - EC01834CF2177AD8BDE489FD5511D73F /* UnmarshalUpdating.swift */, - 797DA5F71FF30F1F36CB728EA07D86CE /* ValueType.swift */, - 4114B6AACBA0B9E7132902C436403BEC /* Support Files */, - ); - name = Marshal; - path = Marshal; - sourceTree = ""; - }; - 7DB346D0F39D3F0E887471402A8071AB = { - isa = PBXGroup; - children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 51A4870BCEAA63E5B4602B4F097A8DC8 /* Development Pods */, - BD3095F190CE7F6B1763B8D9593718D4 /* Frameworks */, - 00E0F19B3926EFDC3BED69C30970490C /* Pods */, - F4653C1CE7983FC8D87793745F4CA0F5 /* Products */, - 6EE1CCCE48AD9922DBFC8E69F35BCC31 /* Targets Support Files */, - ); - sourceTree = ""; - }; - 88000C1FE16BAF8A26217D92F4DC71F3 /* Argo */ = { - isa = PBXGroup; - children = ( - 144962E04851A77F7F0ADE3855B9AC12 /* ArgoDeprecations.swift */, - C6239884AFE3DC00BD7C49C2EFD25B46 /* ArgoMapping.swift */, - ); - name = Argo; - path = Argo; - sourceTree = ""; - }; - 889293C48C50160D065C78A81D0006FA /* SDWebImage */ = { - isa = PBXGroup; - children = ( - 93C5FE81E608B5C32D2CF6427C466BE9 /* ACKReactiveExtensions */, - ); - name = SDWebImage; - sourceTree = ""; - }; - 88E98285E1CEE7C65CC08DE11D8B7DB8 /* Core */ = { - isa = PBXGroup; - children = ( - 91CE2BD9967BB2A97F75D2501EA5D3A2 /* Core.swift */, - ); - name = Core; - path = Core; - sourceTree = ""; - }; - 8AD09635FAC1A0358319803A035A959B /* Support Files */ = { - isa = PBXGroup; - children = ( - 6B0447391FF479F0CF5C4AC6BE28E798 /* Info.plist */, - B6839FFD4AAD85B7EDA4F229E6AF9E63 /* Realm.modulemap */, - 2920E42C255817A6E40496468D7DCC7D /* Realm.xcconfig */, - 59D6B728F4B5D6683F3879D7DDA63938 /* Realm-dummy.m */, - F9DADD469BEF86B09668FD34C201561A /* Realm-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/Realm"; - sourceTree = ""; - }; - 8F33BE6EC19A8BB90C752772B082535E /* Support Files */ = { - isa = PBXGroup; - children = ( - 2DD872E3DA460F034CEAE40B6BC7559D /* Info.plist */, - 1C5ADDD6F855E81D6F9B773C776E3EDA /* Nimble.modulemap */, - A39C238E75ECD4C8358AF6078BEEF931 /* Nimble.xcconfig */, - AF09F3100D0F9E7D24B84A1BF0700FE1 /* Nimble-dummy.m */, - 89C8A2C1910B3237CCE7496E88D0999F /* Nimble-prefix.pch */, - F41849D4EFEC7E703EE4C478513EEBE1 /* Nimble-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Nimble"; - sourceTree = ""; - }; - 93C5FE81E608B5C32D2CF6427C466BE9 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 4239C08209C911B11BCDB9DDD4CF6AF3 /* SDWebImage */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - 94BD0B72B220C1FFD90EDC71A85F1EF8 /* Reachability */ = { - isa = PBXGroup; - children = ( - 4ABC5D71A2A908186B87517B2A07A91B /* RACReachability.swift */, - ); - name = Reachability; - path = Reachability; - sourceTree = ""; - }; - AA89DC7490103AC3F7DA4F2AAB08982C /* Argo */ = { - isa = PBXGroup; - children = ( - 721752886DA62F718878703E4387C37B /* Alternative.swift */, - 47B4D6BE656A53B5B57D0BFB9B020A68 /* Applicative.swift */, - D7CBCD6FCBEC9D5717693AB91F54AC96 /* Argo.swift */, - 0B548C79D533C48D007E1AC4D8658EC9 /* catDecoded.swift */, - 88FCD6FA8617AC21FC97DBD75A967F5A /* Decodable.swift */, - 79E8CB9721CAD2839C372D9DBF7DAF3F /* decode.swift */, - 33CB2E5C87615DE8B3C12CD9493C9868 /* Decoded.swift */, - B6400103CC33210C1B50120D98BE83F0 /* DecodeError.swift */, - 03B463B62FF6326026FA653E42C9926D /* DecodeOperators.swift */, - 09F87A26DBCDFFF48E7D97BF667F86B1 /* Dictionary.swift */, - 3B048703246CB0B6033583241F45580B /* FailureCoalescing.swift */, - D8F4C0E290ADB2B3B26394BA66CA4385 /* flatReduce.swift */, - 7335FCB18987188E521D2CB4729E488B /* Functor.swift */, - 4F9CE6DD770779A4EE2956B3364C4D86 /* JSON.swift */, - 1AAA847DA79BD612A271055247BD13EE /* Monad.swift */, - C5F32DF751D97190D3F56A0809955BAC /* NSNumber.swift */, - 142256C1FF1580722ADF79BC64D3570C /* RawRepresentable.swift */, - 3542FF4AD25D943D1E8DA607A35A7453 /* sequence.swift */, - 8973670C4D50F686E0A23EC6A97FBA02 /* StandardTypes.swift */, - E6D747B971A4C8FD0DF9ABBDD878CB82 /* Support Files */, - ); - name = Argo; - path = Argo; - sourceTree = ""; - }; - ACBE54D9C6D8F699BE557F2402DF76CA /* Support Files */ = { - isa = PBXGroup; - children = ( - 3B7BD69B940C2B7FB43BDDB77643B0B7 /* Info.plist */, - DEB38EF7525DEC9DF35A2CAB77A89C2A /* Runes.modulemap */, - 0C12F0313F515579E91389CB53B065D1 /* Runes.xcconfig */, - 404FFFD3541475853E542117FD585D0C /* Runes-dummy.m */, - 5131C2AB4E890595679303AA065FC3B4 /* Runes-prefix.pch */, - 0413DB276E107A7B52FCB083585DFEAC /* Runes-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Runes"; - sourceTree = ""; - }; - B44411A0E4E1BD26099B55C8BE9E4F8B /* Realm */ = { - isa = PBXGroup; - children = ( - F98732B1434617349CC7A856209E7BD5 /* RealmExtensions.swift */, - ); - name = Realm; - path = Realm; - sourceTree = ""; - }; - BA434637165A4C9BCB4495B564EA52C6 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 1F748482AFC3D42BAC405DC5556ECADE /* UIKit */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - BD3095F190CE7F6B1763B8D9593718D4 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 776B847D8D6EBDA487170EA134742F04 /* Argo.framework */, - 7B029BDAAC30411CD158C72947848BD8 /* Marshal.framework */, - 66A50B6824BF89D3C2F70DBAB43184CA /* Reachability.framework */, - 0E8A2A2A21C0F8A5BE916EDDCE782ED2 /* ReactiveCocoa.framework */, - E72339A6F866D44B06A0DAABEBFC423F /* ReactiveSwift.framework */, - 2DC5C6C2D5404C2EA7B3C1FE285AD756 /* Realm.framework */, - FE8A03AFB4C021181EED12B188D46578 /* RealmSwift.framework */, - 3A7BEE7345BAAC8C6F0C4171128F4B21 /* Result.framework */, - 8EDC7231C6D843E39DC3BD8D5B07DCEA /* Runes.framework */, - 95285970C9E3D84B94D81925791804BF /* SDWebImage.framework */, - BD6D11F483EBEF94F0A85B639F394C59 /* iOS */, - ); - name = Frameworks; - sourceTree = ""; - }; - BD6D11F483EBEF94F0A85B639F394C59 /* iOS */ = { - isa = PBXGroup; - children = ( - 725C00567E177F79A105ED592B9ED0A7 /* Foundation.framework */, - 79AD58BD3EBDD205E05F8B3706FBB64D /* ImageIO.framework */, - DF22416A2052DCD719780514C43D7DD3 /* SystemConfiguration.framework */, - DDA1C3C2C9C97BC2CC36CC727B5A072D /* XCTest.framework */, - ); - name = iOS; - sourceTree = ""; - }; - C2739D02082121948CAA6AA694A7F02A /* Realm */ = { - isa = PBXGroup; - children = ( - D3D3F33E7494D9EC13763E9D34F198A1 /* ACKReactiveExtensions */, - ); - name = Realm; - sourceTree = ""; - }; - C49CBEB4FC2C6A53A12C025B4BA26160 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 88000C1FE16BAF8A26217D92F4DC71F3 /* Argo */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - C6BEC40D6EC8DE20279DB15F6C775247 /* Curry */ = { - isa = PBXGroup; - children = ( - 07B1B4AF823C9F4BA40CFD18D903C114 /* Curry.swift */, - 2C15E69E9D1FB27F573295452DCB4951 /* Support Files */, - ); - name = Curry; - path = Curry; - sourceTree = ""; - }; - C7C4EDF24350E0A368D4ED3EE796ECFC /* Support Files */ = { - isa = PBXGroup; - children = ( - 1DD94FC4C43F3CC593AE8596920824B9 /* Info.plist */, - BF9A947BEFF9F3189347064BED68765E /* Result.modulemap */, - B11C4A93148054BB7AC617A782F1B743 /* Result.xcconfig */, - C3D20A0139A53C62A3196A015F501A35 /* Result-dummy.m */, - A214C3E3D297146D4D0989B560A957F5 /* Result-prefix.pch */, - 6400A354816834BB21D4290FA9222D2B /* Result-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Result"; - sourceTree = ""; - }; - CF08B98229CE45F81470439F806118CC /* Support Files */ = { - isa = PBXGroup; - children = ( - 388382BCC74E82863E7018B4C3949760 /* Info.plist */, - 0C5E10D98138D539CCF68FF7A5EDDAF1 /* ReactiveCocoa.modulemap */, - 5A084AD5E025AAF2890332298FD0D304 /* ReactiveCocoa.xcconfig */, - BDE33B4567F08D97022ECC20CD08799C /* ReactiveCocoa-dummy.m */, - C19BB8E3DD4444877056C7DCE534C187 /* ReactiveCocoa-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/ReactiveCocoa"; - sourceTree = ""; - }; - D3ACF36CF58F495DE54D55DE45C35529 /* Reachability */ = { - isa = PBXGroup; - children = ( - F08E3940E63970B6E942ECD1F9FF1740 /* ACKReactiveExtensions */, - ); - name = Reachability; - sourceTree = ""; - }; - D3D3F33E7494D9EC13763E9D34F198A1 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - B44411A0E4E1BD26099B55C8BE9E4F8B /* Realm */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - DF805A8806DEA6F681575D3CD2868705 /* RealmSwift */ = { - isa = PBXGroup; - children = ( - 2F6B92C6B8D16F1B9375EFBB3DF874C5 /* Aliases.swift */, - BFE4C4809982D8B2B4E0E32574AF0D2C /* Error.swift */, - D9C78D129BD75FF297820F1F1C73A7F6 /* LinkingObjects.swift */, - D8D8C1F9916E66215E027888318CD599 /* List.swift */, - 2925EA57D3DED1B0B8C6F5FF019EE71E /* Migration.swift */, - 7750B0A880CBB6D5D731191421BC46FF /* Object.swift */, - 206E1E12150B32DB317DA4656D2D26AE /* ObjectiveCSupport.swift */, - E410D4DEBDC4874F18B3D7909C7A1696 /* ObjectSchema.swift */, - CEB9CD136253747ACFF7E6ECE6200A47 /* Optional.swift */, - 1A1EDA68881B394DFBBE8D776E4FC50E /* Property.swift */, - 01060E818490024E600D55519EB092E1 /* Realm.swift */, - F6471A97D6C579D396EA6FC04E28003A /* RealmCollection.swift */, - 19BA2C6CAAD1B833C0CA3E10317055BD /* RealmConfiguration.swift */, - 47D7EF3D5D559122CEC7B8050B62E114 /* Results.swift */, - 511961DB43E641DA6E916E03D4AD14F4 /* Schema.swift */, - D48CCF27EDBE23C0E6EC0CA035D560C0 /* SortDescriptor.swift */, - 394D5A2846811D4CBC5ECA82A735FF30 /* SwiftVersion.swift */, - D887D2D35CA24443E4491D8AB9ABF431 /* Sync.swift */, - 340AC7AA1430E9A4AE03BE7D3FF434A2 /* Util.swift */, - 490D1C736E1D9440A38E7162E61B6A1E /* Support Files */, - ); - name = RealmSwift; - path = RealmSwift; - sourceTree = ""; - }; - E1778246C31EB0AB84E858C9CCB851FA /* Argo */ = { - isa = PBXGroup; - children = ( - C49CBEB4FC2C6A53A12C025B4BA26160 /* ACKReactiveExtensions */, - ); - name = Argo; - sourceTree = ""; - }; - E316614E71150DDA26F8A9A87961ED30 /* WebKit */ = { - isa = PBXGroup; - children = ( - 27B5EE3DAD19C6CB453996007A9B3066 /* ACKReactiveExtensions */, - ); - name = WebKit; - sourceTree = ""; - }; - E6D747B971A4C8FD0DF9ABBDD878CB82 /* Support Files */ = { - isa = PBXGroup; - children = ( - 38F0C4AF028762AF6E61DC67F559B4E0 /* Argo.modulemap */, - B1D795BFC1FB929416B4C0C3D2D66E5C /* Argo.xcconfig */, - E00F5ECCFE503D51297AAAC62731DB3F /* Argo-dummy.m */, - 2F3881C29F4D7B36EE3F27584F619186 /* Argo-prefix.pch */, - C95B66D60B294D43AF10B595F8B854CD /* Argo-umbrella.h */, - A2AECBA86246CF8C0DCAE070D4A3BB8A /* Info.plist */, - ); - name = "Support Files"; - path = "../Target Support Files/Argo"; - sourceTree = ""; - }; - E80BDF0AF9838FB08A255170F967C489 /* Support Files */ = { - isa = PBXGroup; - children = ( - CB26D6189CB7AC7831B83F105859FABA /* Info.plist */, - E411A99878B86694C03B7A97DB39278F /* ReactiveSwift.modulemap */, - 6182E9EC62179AFCE72E2ED9B9E2F0D9 /* ReactiveSwift.xcconfig */, - B2FE7CF151309D9D3878192E09F3A3FF /* ReactiveSwift-dummy.m */, - 48871151A824B9F49B5D29098FA2C2DB /* ReactiveSwift-prefix.pch */, - 149397BEB7B8CD201897499DD648374E /* ReactiveSwift-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/ReactiveSwift"; - sourceTree = ""; - }; - EDC3DDD530BD064532119AC6B440CF3F /* Quick */ = { - isa = PBXGroup; - children = ( - 54E89418684BB6D4571366C9D27F6AAE /* Callsite.swift */, - 9EB31B26BDDC740A81CB05AD0E163BDA /* Closures.swift */, - D58B017B22770D3C49FB229911CCA63F /* Configuration.swift */, - F7D8A7566C6856373259F87570F1D754 /* DSL.swift */, - 86FC0E79C1FE92FB2234ADB0BE668E87 /* ErrorUtility.swift */, - 963BB70A82BFE7020C9EC5647DD540FC /* Example.swift */, - 9FAE2BA55456042322852F0EBA66E3E2 /* ExampleGroup.swift */, - 7680BAC933258EEFB43803FE7F3B4BA9 /* ExampleHooks.swift */, - DB81A8BB2D4920F81288AE7615EA7AC1 /* ExampleMetadata.swift */, - 915588B75D0D58472F979621CB7066B7 /* Filter.swift */, - AA8B42E70E3399E2D9030DDA7AB81DF1 /* HooksPhase.swift */, - 10A6B890D72DD8FA3D51FA55D19A7045 /* NSBundle+CurrentTestBundle.swift */, - 9A77A4C2A72C73B57B3099B36D9B02BA /* NSString+QCKSelectorName.h */, - 76E1482324EF76467354EBCD9556D5C3 /* NSString+QCKSelectorName.m */, - E6D9E3AF330175AA70AFDF06735E8B8D /* QCKDSL.h */, - 607DBEB86A79A5476B63B37A8059F2AA /* QCKDSL.m */, - 5CFBECA7EDBB969B477538958A4E4B2D /* Quick.h */, - A1037624D3A582BEEB81981869141420 /* QuickConfiguration.h */, - F00AD52E5921222022AFA34B7A9381CF /* QuickConfiguration.m */, - 5271EC894F3143DFB2B40E1F8339F726 /* QuickSelectedTestSuiteBuilder.swift */, - F4E60902B8DF5048C387EC367747141F /* QuickSpec.h */, - AE00E475E56003AD4B4A2AEE0DE038EA /* QuickSpec.m */, - C47E6B078EDD964EAC0106763ABCCCE4 /* QuickTestSuite.swift */, - A05B079F9AD843FA9C72FF8899904B85 /* String+FileName.swift */, - 1FD4D3B5508FC4EA5098E468A3E41EA5 /* SuiteHooks.swift */, - 555BC55AF5CF61AC1064B2BA8B77D5B9 /* World.h */, - 15927EE2028CAB56CFB99EF18090C7CF /* World.swift */, - 30310BC4025C165E16B519BF5CD34CE9 /* World+DSL.h */, - 05D6C2456AFE9C400319370C741B2E60 /* World+DSL.swift */, - 20ED7AED4F9DC9FD6F9AA9B59F0EDD83 /* XCTestSuite+QuickTestSuiteBuilder.m */, - FE3A6044055B4C9F356C1C999357D43D /* Support Files */, - ); - name = Quick; - path = Quick; - sourceTree = ""; - }; - F08E3940E63970B6E942ECD1F9FF1740 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 94BD0B72B220C1FFD90EDC71A85F1EF8 /* Reachability */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - F3096812C6F2877DE030EB1486AD7B87 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 88E98285E1CEE7C65CC08DE11D8B7DB8 /* Core */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - F4635CB361557CC524C17ECE05A34FE9 /* ACKReactiveExtensions */ = { - isa = PBXGroup; - children = ( - 36EEC49BD4B46D32A0800F1A65203560 /* Marshal */, - ); - name = ACKReactiveExtensions; - path = ACKReactiveExtensions; - sourceTree = ""; - }; - F4653C1CE7983FC8D87793745F4CA0F5 /* Products */ = { - isa = PBXGroup; - children = ( - 7405112230B30EF773FD16BD6C3F6BFE /* ACKReactiveExtensions.framework */, - C44099F5B5E37BEA688D0CDA2A9E3690 /* Argo.framework */, - 2A05AD519EBE844EA875510DEBE70454 /* Curry.framework */, - 770F024D0C91568CD8662CF31067A2D0 /* Marshal.framework */, - DEBB70BB0C957EF815DBA5CF04BE6439 /* Nimble.framework */, - C9E26FF43730A8196ED8C6D674CA0ED2 /* Pods_ACKReactiveExtensions_Example.framework */, - 6039C57D15D206D596DA022F2D775651 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework */, - 45188195842AF0ADF3ECEA1309FD2F4E /* Quick.framework */, - CC575AC39BE285B18F0872ABD0BBF28A /* Reachability.framework */, - 26BD4FA1060B2BACDEA59FBA0725A568 /* ReactiveCocoa.framework */, - 755B77B525264DCF0FAD386170A1DEB8 /* ReactiveSwift.framework */, - 4E70B58DAC696F2C26DE6F3E75D22B24 /* Realm.framework */, - BFCFC133BE9AF98413824FD3CCEE0BB7 /* RealmSwift.framework */, - 03DA588FB6070395B43FDADC81595098 /* Result.framework */, - FDA069771BD828C2580F38C207E31D4D /* Runes.framework */, - DD921AE6FCDD0B567642339C85FF7EBB /* SDWebImage.framework */, - ); - name = Products; - sourceTree = ""; - }; - F77EC3F20FD4F8B8AC87D2FE69024E7C /* UIKit */ = { - isa = PBXGroup; - children = ( - BA434637165A4C9BCB4495B564EA52C6 /* ACKReactiveExtensions */, - ); - name = UIKit; - sourceTree = ""; - }; - FE3A6044055B4C9F356C1C999357D43D /* Support Files */ = { - isa = PBXGroup; - children = ( - 3916AC4D2E4D39199113D17AB7059BE7 /* Info.plist */, - 8E4922058ED17F1F12A2D8541AF8AD34 /* Quick.modulemap */, - 02C78CD73F93EA8B253C2061F339748D /* Quick.xcconfig */, - 73AE9B430B7AAACCF9A62DA30EA4131D /* Quick-dummy.m */, - 650E1C42F742EC5169024DDB0261F042 /* Quick-prefix.pch */, - 2657D40333ACDCFA69A0753858C1099E /* Quick-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Quick"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 038C932F3685BA04374D38570E04A2C0 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - BD7F27110A8B2F68ACBDD25490520BE7 /* ReactiveSwift-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 10EC81F80FC1F055936A6D587D1B0F07 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 75D3BE7F259395437A39A41B3B3F05AE /* ACKReactiveExtensions-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1D190D589EB035AFEF89C8CB4812CC71 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C7A1B68E995EA94EA9E43F0567571260 /* Argo-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2ACF6192E10A038A21EFA2156C9F7EA3 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - F693D0A9E0D05F815A85DC258E75AF8D /* CurrentTestCaseTracker.h in Headers */, - 65F5217D44A557FC16218DE5DE348C35 /* CwlCatchBadInstruction.h in Headers */, - 87DD62F200DAB5E1D701AB9F94D1D422 /* CwlCatchException.h in Headers */, - 0ECEEBC712D404AA6CF1E76A9284BFF9 /* DSL.h in Headers */, - B093484B1637B3D3AF65DF2232FDBADC /* mach_excServer.h in Headers */, - 76036D32625A56D480D84AA46961EF91 /* Nimble-umbrella.h in Headers */, - 469E9C3ED9FD6009F7C9AAF9E537E212 /* Nimble.h in Headers */, - 917949F596E1188261FC59214782C3D9 /* NMBExceptionCapture.h in Headers */, - 27B262F95D3CF9E3C74541A41929691C /* NMBStringify.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2FCCA3CF0A8450B70CC6AA54C610F841 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C6825DA2061A1ABE3E81472FC8B71D69 /* NSData+ImageContentType.h in Headers */, - B5D27A8F63B37DE88C0F521218B7F66D /* NSImage+WebCache.h in Headers */, - DE68DF962964EF8F48B3008054DBA6F4 /* SDImageCache.h in Headers */, - 14073D5591E42EFF0B535DBC24DC8F71 /* SDImageCacheConfig.h in Headers */, - 8EAC470AC832E141796F9D59C5C2F962 /* SDWebImage-umbrella.h in Headers */, - 8D5AFB85F283F350E04DCF8F39ED65BA /* SDWebImageCompat.h in Headers */, - 6F5627AEEF49A667AD9398805AE5038A /* SDWebImageDecoder.h in Headers */, - 53F32D934AD582642EACF4374DEA778B /* SDWebImageDownloader.h in Headers */, - 9C843F1B007EEE9E2E44BB04A9D45D6F /* SDWebImageDownloaderOperation.h in Headers */, - 026C120AAA7AA799CBE340B33D83D0A3 /* SDWebImageManager.h in Headers */, - 8FDAF52E5935BEF09109C8F8882CBDEF /* SDWebImageOperation.h in Headers */, - 6812F52EC81468AD671295EDA4C068D2 /* SDWebImagePrefetcher.h in Headers */, - 429CBF05F23D7C892F041950B40B34B0 /* UIButton+WebCache.h in Headers */, - D06E63966143D6B1035F5BCC4DE097D0 /* UIImage+GIF.h in Headers */, - 42949F801C0D3D6B7A45049A2AA1F82E /* UIImage+MultiFormat.h in Headers */, - CB33C7EB63C52EA65AB2E0E783BD0F4C /* UIImageView+HighlightedWebCache.h in Headers */, - D01D557A69E81674354B47FEBD5367F2 /* UIImageView+WebCache.h in Headers */, - 6860A472B8C0EDF4C3FE12596E9A9DB3 /* UIView+WebCache.h in Headers */, - 574C9B986CB151FB26A5FB44CD79149A /* UIView+WebCacheOperation.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4DD9B87ACCB4FBB05681F6C0B54A6ED7 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - BD360A232FD63096C5CDB1735052FE17 /* Marshal-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6651E6CA0A2C12165BD8EC569CA43E47 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 6BB08C533B9F31BB8C8BF1DD2395E3B9 /* Pods-ACKReactiveExtensions_Example-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6E96DB3B2D401DAD2C30D780C3E1FB01 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 6486FF457E5C3F122BC98A4DD7B80CE8 /* Realm.h in Headers */, - B9F9DF2277C1031310BE0F0A4523453E /* RLMAccessor.h in Headers */, - 3537DDF9A83CA1483C81D408C0EE2FEE /* RLMArray.h in Headers */, - 1DF1AC537F76166AB870A75A5154E3DF /* RLMArray_Private.h in Headers */, - F86CA9F23356AF5E227F45E3D6903216 /* RLMCollection.h in Headers */, - A69E61CE8F3B0B58285AE941F5046C9C /* RLMConstants.h in Headers */, - BB481B9492DBF78300596180623575D8 /* RLMListBase.h in Headers */, - 48C2D1A7CA70E0705BAAC5825543C696 /* RLMMigration.h in Headers */, - 0BBECF3451BA6FE8CB28BAFCE21F3429 /* RLMMigration_Private.h in Headers */, - 185D2B0AF8D9889A2B17F9369C1D6441 /* RLMObject.h in Headers */, - 67C9D041D08BD84FD7A7AB830FE94F39 /* RLMObject_Private.h in Headers */, - 5C593FC7DC74D282A26500CB15613CDD /* RLMObjectBase.h in Headers */, - 367692E23AA98BB10DB933E05955647D /* RLMObjectBase_Dynamic.h in Headers */, - 23B45D711EBC45C776AA84A54AD3A0FE /* RLMObjectSchema.h in Headers */, - B3CC6C919614AA5981B0845892914191 /* RLMObjectSchema_Private.h in Headers */, - 1C563FEA1A1D3D29C5C41377CEC9037C /* RLMObjectStore.h in Headers */, - 11DDB2DB3F2C88EFC12DB242CDF47568 /* RLMOptionalBase.h in Headers */, - 799BF35B297C38560B206DA38DBC1BC2 /* RLMPlatform.h in Headers */, - E559A2BC2DEE2CD8A1AFD646921456C7 /* RLMProperty.h in Headers */, - 11DDF57ABADC4FAB95DA443AFC12AF47 /* RLMProperty_Private.h in Headers */, - 1ECC7B032BB9DBD2F63AC868DC5E823D /* RLMRealm.h in Headers */, - F5464A5C3C64326209B55E4B23FA6B46 /* RLMRealm_Dynamic.h in Headers */, - 70DAF19A0935877A3A8110FF0E6C5BA8 /* RLMRealm_Private.h in Headers */, - 886E986B10F6FA5D0F6C61148C219389 /* RLMRealmConfiguration+Sync.h in Headers */, - 3975A5075A67CBD8BDF04C69F64B2C7A /* RLMRealmConfiguration.h in Headers */, - 10C007DB3ED975F6995738B17E02A0CC /* RLMRealmConfiguration_Private.h in Headers */, - B3C6DC1ABA6D315DD8D6BC5A0F408BBE /* RLMResults.h in Headers */, - CCA07256E95D4549E1B676A49DE9FD31 /* RLMResults_Private.h in Headers */, - 9531D50971D4F3A23EE8B7D19536E351 /* RLMSchema.h in Headers */, - A27C038A5FB17B7A95CD328EEC66B37B /* RLMSchema_Private.h in Headers */, - 4D744EF8A360A1389BCD8DF0B6FC0273 /* RLMSyncConfiguration.h in Headers */, - FE0960CB3A0995754417914479949CAA /* RLMSyncConfiguration_Private.h in Headers */, - 5C1C2E5A285203E728D90731DFD3C433 /* RLMSyncCredentials.h in Headers */, - 0452F06F534451551D51070D6FF46B19 /* RLMSyncManager.h in Headers */, - EF31FCE477E3637A878F6AA985BEBEFF /* RLMSyncManager_Private.h in Headers */, - 5C96F2C33890F43BD0CFD19D9B656AE1 /* RLMSyncPermissionChange.h in Headers */, - 1C4E3E98C861706366D9F74A6417AEBF /* RLMSyncPermissionChange_Private.h in Headers */, - 3DA9FD766BBE43ABF268BDABB762F11F /* RLMSyncSession.h in Headers */, - 842A7A8A9CE04F6991A5231C56683469 /* RLMSyncUser.h in Headers */, - 766C0FF607A75C9CED8800DC806DD5A0 /* RLMSyncUtil.h in Headers */, - 37220ED6E18CD75B6957A68B8D8FC702 /* RLMSyncUtil_Private.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7F8E3C305EF292BDD1D5973004E08FC8 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C84CF51F332CDEC87E64A81BE83DA663 /* RealmSwift-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 83C79BC6718483EB76C6D4C23AAFE5A8 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - BAAE8C77EE92C1E16375D215401708DD /* Result-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8E9933E3340958A89E09434C577ED2D1 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0B999D2E8FA80F48D33C387CD2E9977F /* Curry-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A2AA7BEE116860FACB9B964A2872133B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 78E1ED7C0CDBB76BAEBBDA0491CF4AC0 /* Reachability-umbrella.h in Headers */, - 16A2ABB2ABFD2D206A5D1EF68B4B2FA4 /* Reachability.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AAEE5A5BBC8BEBF8AC880E46F43E6B39 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C20BE5FF4A0626CCDB4A73DC55ACDD66 /* Runes-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B30D2FCDEB4CC0909E62C0F8B728693A /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E88C2850063783DB767F109BD95AC310 /* ObjCRuntimeAliases.h in Headers */, - 6164192DED4986BA2338CD392AB24845 /* ReactiveCocoa.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C62738C049BA7D6EDE60410F1B738C0F /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 9C7EBA9F477CF43D497E502209360B14 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EF9643C0B44C254DDC536E56D31A93AB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CBCA79D60C523A0239828C53E17BB892 /* NSString+QCKSelectorName.h in Headers */, - 71B113AB3D0C0DEFAEF9A32F75753EA7 /* QCKDSL.h in Headers */, - E42A8DC24A5489DFCE54941E1EAFF183 /* Quick-umbrella.h in Headers */, - 4F329464CFE2D937CBA77A6CAD12054D /* Quick.h in Headers */, - 5E7520F9D135C952654E24FF28398EA6 /* QuickConfiguration.h in Headers */, - A1FA40A47007CABA456102535530AF1B /* QuickSpec.h in Headers */, - F8F0A3F931CCF20B92657930620C717E /* World+DSL.h in Headers */, - 8186F1339FA8E4E69A2A53038C96CABA /* World.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 1321E318D10CFDC9F5B93A7952492CCD /* Nimble */ = { - isa = PBXNativeTarget; - buildConfigurationList = B1DBAFB75A3AF98C8C6B0863BDC7A2E3 /* Build configuration list for PBXNativeTarget "Nimble" */; - buildPhases = ( - 3C4AABA28564F6F29FE8E3F38226690A /* Sources */, - DBE2CE2F5ED086FC1DD44D4B176AEA5B /* Frameworks */, - 2ACF6192E10A038A21EFA2156C9F7EA3 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Nimble; - productName = Nimble; - productReference = DEBB70BB0C957EF815DBA5CF04BE6439 /* Nimble.framework */; - productType = "com.apple.product-type.framework"; - }; - 1E5CBD4CF0019B7B128A1E5EDF9AC9F2 /* Pods-ACKReactiveExtensions_Example */ = { - isa = PBXNativeTarget; - buildConfigurationList = 99FCB002E66D63F1F7B5E45F9E9675CB /* Build configuration list for PBXNativeTarget "Pods-ACKReactiveExtensions_Example" */; - buildPhases = ( - C5EFE7D8EADC33B56144700290EF7ED9 /* Sources */, - 69FCD5E0AABA3F8DBB1004DF32E31FF0 /* Frameworks */, - 6651E6CA0A2C12165BD8EC569CA43E47 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - F905316CAE5764F3CAB887E9F812F8DD /* PBXTargetDependency */, - F24610420965E1A62753ED451581EE44 /* PBXTargetDependency */, - D24EA64D3844E8BE5A178431D29E7CBD /* PBXTargetDependency */, - A64370BD01242D6B54FBD5549385BD47 /* PBXTargetDependency */, - 52373DE9E9033CF7B36AF50C66BCB31D /* PBXTargetDependency */, - CC7C13C25A80D4978A348698E7B1FBAF /* PBXTargetDependency */, - 0663AF9F998396D80936468DB167EA31 /* PBXTargetDependency */, - 62665E4894AD8D03F1AA333A8C245929 /* PBXTargetDependency */, - 7E55C0EEDDDF83B1AB6C9CA15E2395E0 /* PBXTargetDependency */, - 314E6C2DF88E43F1047E472C10EC0C0A /* PBXTargetDependency */, - 8FA4D696E27722E08FFBE5D18D431486 /* PBXTargetDependency */, - ); - name = "Pods-ACKReactiveExtensions_Example"; - productName = "Pods-ACKReactiveExtensions_Example"; - productReference = C9E26FF43730A8196ED8C6D674CA0ED2 /* Pods_ACKReactiveExtensions_Example.framework */; - productType = "com.apple.product-type.framework"; - }; - 378E1575B1A77DB0CC90AD1E5B4E59B9 /* Curry */ = { - isa = PBXNativeTarget; - buildConfigurationList = D3805B445D3E6689AE33CEAB50F7DE9F /* Build configuration list for PBXNativeTarget "Curry" */; - buildPhases = ( - 0CCB6776784A4AF4F44923F6721BC8FC /* Sources */, - E1656C806D61CD0B3B68DBC573EB213D /* Frameworks */, - 8E9933E3340958A89E09434C577ED2D1 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Curry; - productName = Curry; - productReference = 2A05AD519EBE844EA875510DEBE70454 /* Curry.framework */; - productType = "com.apple.product-type.framework"; - }; - 3DE0C97A2313CC9DA982FBC2C12E6B42 /* Argo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 29B7D73F2439424DC5BB3EF0CF0065EB /* Build configuration list for PBXNativeTarget "Argo" */; - buildPhases = ( - B451CA9BFD8C4AAF3103E72BB62918C4 /* Sources */, - 09339920AAC2C898CF062C08E8504BDF /* Frameworks */, - 1D190D589EB035AFEF89C8CB4812CC71 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 2903774E749981E693E3E2FC63AAF836 /* PBXTargetDependency */, - ); - name = Argo; - productName = Argo; - productReference = C44099F5B5E37BEA688D0CDA2A9E3690 /* Argo.framework */; - productType = "com.apple.product-type.framework"; - }; - 3E12B2B47078F77F5CB8A10C0EF8C1AF /* Reachability */ = { - isa = PBXNativeTarget; - buildConfigurationList = 148A7783D63EAB41DFDBC1895EDFDDE5 /* Build configuration list for PBXNativeTarget "Reachability" */; - buildPhases = ( - 7A5E66E0250085CFF8C957AF18C0D222 /* Sources */, - 0F6BA1262E8C8EE1060A0970B4EDA970 /* Frameworks */, - A2AA7BEE116860FACB9B964A2872133B /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Reachability; - productName = Reachability; - productReference = CC575AC39BE285B18F0872ABD0BBF28A /* Reachability.framework */; - productType = "com.apple.product-type.framework"; - }; - 540B755C72E99D2B6A76D13262796807 /* SDWebImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 254AF3FD9BB6B7CB2327611FF034D70E /* Build configuration list for PBXNativeTarget "SDWebImage" */; - buildPhases = ( - AE45CD351DEBDD9F2DAE65FF8D523688 /* Sources */, - 42FEE9C4C2A3C7EC571A1A1A3073BB7D /* Frameworks */, - 2FCCA3CF0A8450B70CC6AA54C610F841 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SDWebImage; - productName = SDWebImage; - productReference = DD921AE6FCDD0B567642339C85FF7EBB /* SDWebImage.framework */; - productType = "com.apple.product-type.framework"; - }; - 5E29F3F45BD6B823A2EC56ECA2397070 /* ReactiveCocoa */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4BDA66AD220ABFE08994873139073A67 /* Build configuration list for PBXNativeTarget "ReactiveCocoa" */; - buildPhases = ( - 82131165B4533445C05EC8166BA4EA53 /* Sources */, - 6BC1965B9C665C0703945A6BFA8DEEEA /* Frameworks */, - B30D2FCDEB4CC0909E62C0F8B728693A /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - E136F29D457F34E5132C03A47AA3D2EB /* PBXTargetDependency */, - 507A2518C2065B74C9998C50DFDA914C /* PBXTargetDependency */, - ); - name = ReactiveCocoa; - productName = ReactiveCocoa; - productReference = 26BD4FA1060B2BACDEA59FBA0725A568 /* ReactiveCocoa.framework */; - productType = "com.apple.product-type.framework"; - }; - 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2CE93F5BC6127A8D006A637C0612EC87 /* Build configuration list for PBXNativeTarget "Runes" */; - buildPhases = ( - 186946DD6F869759DCEC3B03ACB0D6AD /* Sources */, - E76ADB945D5AA52797580E298B9F1419 /* Frameworks */, - AAEE5A5BBC8BEBF8AC880E46F43E6B39 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runes; - productName = Runes; - productReference = FDA069771BD828C2580F38C207E31D4D /* Runes.framework */; - productType = "com.apple.product-type.framework"; - }; - 8107DB93200934B6DEFD700F43910AC7 /* Result */ = { - isa = PBXNativeTarget; - buildConfigurationList = B0BEB80584AD389708E7629F1320AEF8 /* Build configuration list for PBXNativeTarget "Result" */; - buildPhases = ( - 86F290CEB84F7D8700982794E92D0A2A /* Sources */, - 5126F3ADB8F1EF2A4F09AC5235376EEE /* Frameworks */, - 83C79BC6718483EB76C6D4C23AAFE5A8 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Result; - productName = Result; - productReference = 03DA588FB6070395B43FDADC81595098 /* Result.framework */; - productType = "com.apple.product-type.framework"; - }; - 8C3D90B09D20CB4C804DD2F29D525C27 /* RealmSwift */ = { - isa = PBXNativeTarget; - buildConfigurationList = D24F5DA1081D06F59DB164D62A62ED35 /* Build configuration list for PBXNativeTarget "RealmSwift" */; - buildPhases = ( - 8E138038DA4E1473DF279EEBD6771818 /* Sources */, - FA4B33CED0F7A897CFB617B0B45554E6 /* Frameworks */, - 7F8E3C305EF292BDD1D5973004E08FC8 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 831962E00E58B35F0A3BAAC465B79C0B /* PBXTargetDependency */, - ); - name = RealmSwift; - productName = RealmSwift; - productReference = BFCFC133BE9AF98413824FD3CCEE0BB7 /* RealmSwift.framework */; - productType = "com.apple.product-type.framework"; - }; - 96D93470C408341136D1AE696D2459E6 /* Quick */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1B163EA84BC35A17D33D319232A9E8D4 /* Build configuration list for PBXNativeTarget "Quick" */; - buildPhases = ( - 64B2E0B5620423B654DFFE82B57C8C78 /* Sources */, - 4C16868C430A16DED48B21AEF479D04C /* Frameworks */, - EF9643C0B44C254DDC536E56D31A93AB /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Quick; - productName = Quick; - productReference = 45188195842AF0ADF3ECEA1309FD2F4E /* Quick.framework */; - productType = "com.apple.product-type.framework"; - }; - B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */ = { - isa = PBXNativeTarget; - buildConfigurationList = 275AC031F358FD9C1A1945F3B3F45450 /* Build configuration list for PBXNativeTarget "Realm" */; - buildPhases = ( - 35A5ADAF10E45FC257A87FF9C724D975 /* Sources */, - 62C3B53A7993272A742952C3F5E108BD /* Frameworks */, - 6E96DB3B2D401DAD2C30D780C3E1FB01 /* Headers */, - CD4364B2F240FB4B7758A102B4805960 /* Copy . Private Headers */, - F4BEC5AA00AE5B9B9FD5EAB69A468543 /* Copy . Public Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Realm; - productName = Realm; - productReference = 4E70B58DAC696F2C26DE6F3E75D22B24 /* Realm.framework */; - productType = "com.apple.product-type.framework"; - }; - D6A1B9EB7A50D88E5565BEFC1946E68B /* Marshal */ = { - isa = PBXNativeTarget; - buildConfigurationList = 580701FC11C60A37428C21E5E6CD40D5 /* Build configuration list for PBXNativeTarget "Marshal" */; - buildPhases = ( - 9C703F3EC1885D7A72CDA26B517AF2EC /* Sources */, - BB660921F4ADB723015A48AE39A34B4A /* Frameworks */, - 4DD9B87ACCB4FBB05681F6C0B54A6ED7 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Marshal; - productName = Marshal; - productReference = 770F024D0C91568CD8662CF31067A2D0 /* Marshal.framework */; - productType = "com.apple.product-type.framework"; - }; - DE3EBDE84D7632BA2C58988A7A5C141B /* ACKReactiveExtensions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 505E5D5BE85FB65F3CCC3748B677ADB5 /* Build configuration list for PBXNativeTarget "ACKReactiveExtensions" */; - buildPhases = ( - 1A171ABB96DF68582732209EC4C85044 /* Sources */, - 0C75D523EFEDDA8D8D1B3F80210DA1D1 /* Frameworks */, - 10EC81F80FC1F055936A6D587D1B0F07 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 8CCE78DF4DC4E388382FBBE35D8D1868 /* PBXTargetDependency */, - 255CE31E43151486D601CFB1AD21E229 /* PBXTargetDependency */, - 7B9587C3152AA4572E6887D9D893F16C /* PBXTargetDependency */, - EC5F98D1CD047EAF59CE522033432FC4 /* PBXTargetDependency */, - 3AB4D72A2818CA460ADCF1418EB8A015 /* PBXTargetDependency */, - AC396207E9FBF23ABB13EF8E0D8BF1EE /* PBXTargetDependency */, - 6C3A29D21310618A80EC41503A83EE39 /* PBXTargetDependency */, - EEDB4A7EF92F037CDD37AC16274C47C0 /* PBXTargetDependency */, - C0ADDD5CA888FC44E5ECE93CC27AC0A1 /* PBXTargetDependency */, - 511AAA384CAF9DD984D69859AB9FCB45 /* PBXTargetDependency */, - ); - name = ACKReactiveExtensions; - productName = ACKReactiveExtensions; - productReference = 7405112230B30EF773FD16BD6C3F6BFE /* ACKReactiveExtensions.framework */; - productType = "com.apple.product-type.framework"; - }; - E0C6BFFCC628FA6BF8E3D3C9C56D9ED7 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9980AE4F9112C78250AE09BFD6E89A9B /* Build configuration list for PBXNativeTarget "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests" */; - buildPhases = ( - E33FAC6F70FB7A125F4B4878336CF34D /* Sources */, - 34091F7A20179AF439E5793B51FCF406 /* Frameworks */, - C62738C049BA7D6EDE60410F1B738C0F /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 096C8A380708FE06DC8EB7969AF085B2 /* PBXTargetDependency */, - CEE94527EBCE1C929CDACB99A21E0835 /* PBXTargetDependency */, - 5330A14AF002FBE9CA544949536BC9ED /* PBXTargetDependency */, - 415A95FFA808E41A6FE70F2C0F1B6E36 /* PBXTargetDependency */, - 35E4B04E4BDB0F2B51DC68DE0FF35263 /* PBXTargetDependency */, - F94E8763881C765715E69B08A94380C4 /* PBXTargetDependency */, - A45174844D91D0284691BCAC49AD6AF7 /* PBXTargetDependency */, - A01DB47DA295C7BB960691F89DBAF339 /* PBXTargetDependency */, - F860A32EAE85A201262D45B6A286762C /* PBXTargetDependency */, - EC07B45B6D75D458A3BDDB4D52A3F385 /* PBXTargetDependency */, - 9C7F0AA9AE279CB4B692340981CC0190 /* PBXTargetDependency */, - 2070A6E4F49595A4A506F0AC4A526970 /* PBXTargetDependency */, - F8EA201877886AD848505482C7F0E6A2 /* PBXTargetDependency */, - 1AAE113CFDF84651E8C611CFEC0F7EAB /* PBXTargetDependency */, - ); - name = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests"; - productName = "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests"; - productReference = 6039C57D15D206D596DA022F2D775651 /* Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests.framework */; - productType = "com.apple.product-type.framework"; - }; - F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */ = { - isa = PBXNativeTarget; - buildConfigurationList = 64C97413B9489AAF9EE36465E0C164BF /* Build configuration list for PBXNativeTarget "ReactiveSwift" */; - buildPhases = ( - 5820458A2A51811763E6C69788202609 /* Sources */, - 7AB9AD551FAE028D9517461DA1CEA573 /* Frameworks */, - 038C932F3685BA04374D38570E04A2C0 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 85D36FAC3C69573AA831A22A7CF98712 /* PBXTargetDependency */, - ); - name = ReactiveSwift; - productName = ReactiveSwift; - productReference = 755B77B525264DCF0FAD386170A1DEB8 /* ReactiveSwift.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; - }; - buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = F4653C1CE7983FC8D87793745F4CA0F5 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DE3EBDE84D7632BA2C58988A7A5C141B /* ACKReactiveExtensions */, - 3DE0C97A2313CC9DA982FBC2C12E6B42 /* Argo */, - 378E1575B1A77DB0CC90AD1E5B4E59B9 /* Curry */, - D6A1B9EB7A50D88E5565BEFC1946E68B /* Marshal */, - 1321E318D10CFDC9F5B93A7952492CCD /* Nimble */, - 1E5CBD4CF0019B7B128A1E5EDF9AC9F2 /* Pods-ACKReactiveExtensions_Example */, - E0C6BFFCC628FA6BF8E3D3C9C56D9ED7 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests */, - 96D93470C408341136D1AE696D2459E6 /* Quick */, - 3E12B2B47078F77F5CB8A10C0EF8C1AF /* Reachability */, - 5E29F3F45BD6B823A2EC56ECA2397070 /* ReactiveCocoa */, - F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */, - B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */, - 8C3D90B09D20CB4C804DD2F29D525C27 /* RealmSwift */, - 8107DB93200934B6DEFD700F43910AC7 /* Result */, - 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */, - 540B755C72E99D2B6A76D13262796807 /* SDWebImage */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 0CCB6776784A4AF4F44923F6721BC8FC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B7C477EDDDC724E7EBAE9893E4467713 /* Curry-dummy.m in Sources */, - 02591775914FEC8F71F091689667029A /* Curry.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 186946DD6F869759DCEC3B03ACB0D6AD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7CE3CE78117685C574CDBC1059E93B95 /* Array.swift in Sources */, - 125DDC49328BC08C93205BD98DB0CFF7 /* Optional.swift in Sources */, - 6793F92D394368B5122346D40A26AF5D /* Runes-dummy.m in Sources */, - 019ECB09A9E31D2A4256499031A0C930 /* Runes.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1A171ABB96DF68582732209EC4C85044 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 707877BCC4E5F20581E5ADEF4C4ADE4E /* ACKReactiveExtensions-dummy.m in Sources */, - 9DDAA27C7BD1BC420D606A88F9949B58 /* ArgoDeprecations.swift in Sources */, - 6CAE17DF3C4F68FE927E58429FC22D4E /* ArgoMapping.swift in Sources */, - F52F5D7F862F1BA244BCE80CDAD92C38 /* Core.swift in Sources */, - 7AE0746CCA5D2EFB3CE4DD703DB8207E /* Deprecations.swift in Sources */, - 7FB2ECBEAC0D5F93B278A7F58F168D4B /* MarshalMapping.swift in Sources */, - 9E09AF4AB2B428CDD1B45CE39ADD6706 /* RACReachability.swift in Sources */, - 04BB0E73573A81B23B3393B0912DD037 /* RealmExtensions.swift in Sources */, - 4DA99736E2B23EE647F695A3AAE4F693 /* SDWebImage+RAC.swift in Sources */, - 6F4B3812DD04451FC89150E11156113D /* UIKitExtensions.swift in Sources */, - F48D38DD2EBA98D8EBFCF74AA0DD1CEC /* WebKitExtensions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 35A5ADAF10E45FC257A87FF9C724D975 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 85FF8757FD497275E89406C1A645DB3C /* collection_change_builder.cpp in Sources */, - FE4AF0E2D0E1E345B5F3C22F3AE323D6 /* collection_notifications.cpp in Sources */, - 8BECFAB439E0E23A0788E73819FD0C99 /* collection_notifier.cpp in Sources */, - 9996C1F28B2CE2EF5B81DB9A9A6C7213 /* external_commit_helper.cpp in Sources */, - 3E42FF29784DB08DFBC8897C969F509C /* format.cpp in Sources */, - C0CDAF5BAF254A851596E52FAF38E8B2 /* handover.cpp in Sources */, - D1B581D92B0A4F072D507107AE29A868 /* index_set.cpp in Sources */, - E834B61262C2E6907A070CE144025B96 /* keychain_helper.cpp in Sources */, - 6B54C8A8B1F68CD253E26A8845C994AB /* list.cpp in Sources */, - C25ADF86A646FC616F96E8CA06192B19 /* list_notifier.cpp in Sources */, - 686CD02C78B4819E0D90F8A2FBFC4F12 /* object_schema.cpp in Sources */, - A1E786FD32DC1326DCFAA2B8B29B35E2 /* object_store.cpp in Sources */, - F2A57ADA158E56674CF2B6D0282A88BD /* placeholder.cpp in Sources */, - 84A77035E531CBEA183F49DA69CA7988 /* Realm-dummy.m in Sources */, - A10F09E52A0AA09EDC77BF115B5CACD6 /* realm_coordinator.cpp in Sources */, - 638A4E4B18F6E5A359B5F2B8FF231FB8 /* results.cpp in Sources */, - 3C06CFA9CE59B5A39FF7D9CCA1671DB8 /* results_notifier.cpp in Sources */, - 7A855F80FA047F2B1921E7A0710DB4B4 /* RLMAccessor.mm in Sources */, - FA3BDC52A3FA323A4ABA7A088AB017C5 /* RLMAnalytics.mm in Sources */, - 33FF2FB35C214948E64A213CCF3DBBC5 /* RLMArray.mm in Sources */, - 11F5A28A612C7CE8E57C31F0AEA9FCAF /* RLMArrayLinkView.mm in Sources */, - 07D7DE59C1369D3790FACB0847738FA5 /* RLMAuthResponseModel.m in Sources */, - BC9025FC6C536CA7CF2287A6B5FA2DE4 /* RLMClassInfo.mm in Sources */, - A89CBB749AD66074ED365475C492F511 /* RLMCollection.mm in Sources */, - A0BC3C79604FEC79CBC351BC79EE52A8 /* RLMConstants.m in Sources */, - 5F85FA3B4239C013EC015B225A8405D4 /* RLMListBase.mm in Sources */, - 7D696B3DF6E33D44478F2A794B82E44C /* RLMMigration.mm in Sources */, - 4B2A28C3B7D8196D0D668639EF054A00 /* RLMNetworkClient.m in Sources */, - 33F9866278D0CE3228BB9DD34FEFFBD3 /* RLMObject.mm in Sources */, - 448ADC334870B554FF36A8B7A44E5FA3 /* RLMObjectBase.mm in Sources */, - D72577F4B267DDCD354BE852C172A986 /* RLMObjectSchema.mm in Sources */, - BB13C29F36F88E24711C0D790C3CFF92 /* RLMObjectStore.mm in Sources */, - D7B86895FEFA5E23D5727970A1ECBBEE /* RLMObservation.mm in Sources */, - 83030E8C22928BB6014799EAFA54BEDC /* RLMOptionalBase.mm in Sources */, - 3A698AFE74B42160CF93124938F698AF /* RLMPredicateUtil.mm in Sources */, - D255839B59A184FDC60BFA1ED5F77D70 /* RLMProperty.mm in Sources */, - 5D8E324A5B6F5DF8A988DBF19B8BB81C /* RLMQueryUtil.mm in Sources */, - B0E4C731E1B85307EDDF547A51532016 /* RLMRealm.mm in Sources */, - 0CF70D2D57B6C4E2F188497BB68302B3 /* RLMRealmConfiguration+Sync.mm in Sources */, - 45C4C7AE020F6045F18ECC1480A8B429 /* RLMRealmConfiguration.mm in Sources */, - D7F7FC24D36B21EF375AAFD627570108 /* RLMRealmUtil.mm in Sources */, - 4079D165294FC444BE339C0DF23813B4 /* RLMResults.mm in Sources */, - BED3F012B1EDED44A23FBF2A3CA23CB1 /* RLMSchema.mm in Sources */, - A042E4E8708798EE81C7EB2D7EE3C2B8 /* RLMSwiftSupport.m in Sources */, - 11D48C81BE09541E54A4174D45E2B5B1 /* RLMSyncConfiguration.mm in Sources */, - 7BE5AB45B8861E689B7D3F1434A4873A /* RLMSyncCredentials.m in Sources */, - 75171AF1BDA20F22D864641F10968785 /* RLMSyncErrorResponseModel.m in Sources */, - D60B6F772463491CCCF5F44561DB986B /* RLMSyncManager.mm in Sources */, - 3169D990CA17FD66CC91665888341184 /* RLMSyncPermissionChange.m in Sources */, - 1D62A79936A0BFA068ACED23D6091C6D /* RLMSyncSession.mm in Sources */, - 23E386D2F3424DB21F3B744ED455CA96 /* RLMSyncSessionRefreshHandle.mm in Sources */, - 56600FE41D89E6F6B1A4953A4CEFF64C /* RLMSyncUser.mm in Sources */, - 64D6D3C4C06DEE74FCAEF12A9810BA1D /* RLMSyncUtil.mm in Sources */, - 6974BCB4113383F63F4D654F60D97AC9 /* RLMTokenModels.m in Sources */, - 6BAA81150FFC0127929E1734953C1EBD /* RLMUpdateChecker.mm in Sources */, - 12D80FBF10D3D3A517689E9CABD6E77E /* RLMUtil.mm in Sources */, - 6AADE869DC160B2B1DEAEB77B7E474F5 /* schema.cpp in Sources */, - CCF1BE4015BB558C6B1687F3B0CBA0F1 /* shared_realm.cpp in Sources */, - 1527F0D2E4CE817D3F98AB2EC0C25AC0 /* sync_file.cpp in Sources */, - 0ADD5E09DA2E1537FA19E10893C86D4E /* sync_manager.cpp in Sources */, - 4ECC3799B8C8CFED57C4B1F8B853D452 /* sync_metadata.cpp in Sources */, - C09D570B3A79DA617D07C9B6D2323F57 /* sync_session.cpp in Sources */, - FDC5E9CA22F2BB8936B753A35A1F56A5 /* sync_user.cpp in Sources */, - 0C309D486F03BE8D49BDB723BBB583FA /* thread_confined.cpp in Sources */, - 9CD91D90F932A086B01FBE19417A3424 /* transact_log_handler.cpp in Sources */, - 3BFDA793D5B648D0AB5CC863A73AD84C /* weak_realm_notifier.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3C4AABA28564F6F29FE8E3F38226690A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 047A68C646E00EB6D7D4D7343B801D09 /* AdapterProtocols.swift in Sources */, - DCEE854E62441E78FED15CC994497F61 /* AllPass.swift in Sources */, - 74FD712F3B503891B6BD9E5CD287E481 /* AssertionDispatcher.swift in Sources */, - F9E05A63D447B51E008B89731192FE7F /* AssertionRecorder.swift in Sources */, - AC29CC89E22273BF0D0DC2C841B7524C /* Async.swift in Sources */, - 551440A0F92574039C1D2EB39227D6B8 /* AsyncMatcherWrapper.swift in Sources */, - F60D221B548716DF35193FC2CF244676 /* BeAKindOf.swift in Sources */, - A448F837592E21D9387322E8DA0DD93F /* BeAnInstanceOf.swift in Sources */, - 9544A4EEC2A8448743ECA9981F88B60F /* BeCloseTo.swift in Sources */, - 9AF235C16362BA00BFBF12147907E953 /* BeEmpty.swift in Sources */, - AB255C27EF10E742C6567775022F49D5 /* BeginWith.swift in Sources */, - 07722FBCF6B380961B9D2832D5883F45 /* BeGreaterThan.swift in Sources */, - 1C50F54510D5C2B2AD84D7B74A6EDEBB /* BeGreaterThanOrEqualTo.swift in Sources */, - A33F1754198E8E8CCC7087F6176FFDC8 /* BeIdenticalTo.swift in Sources */, - 6E397D9FB11A47E48D70287D734B12B2 /* BeLessThan.swift in Sources */, - FAB4ECE0C5039D99BB7173880670871D /* BeLessThanOrEqual.swift in Sources */, - 0AEC20AACF9B10846830274E3B2AA6FD /* BeLogical.swift in Sources */, - 599669823A2EED2928C77F301F6B0515 /* BeNil.swift in Sources */, - 78F3DE174B4F8D368EF8EEFD7EE62087 /* BeVoid.swift in Sources */, - 8507F4BF7437EB40A3626EDCC68BFF6D /* Contain.swift in Sources */, - 737E19F3254F5929263982C29237C0BA /* CwlBadInstructionException.swift in Sources */, - 3915DBB4731CB17B255A7FE86E240B6E /* CwlCatchBadInstruction.m in Sources */, - 6CDBA48C3A8621E4EE1DAFFE240F0D82 /* CwlCatchBadInstruction.swift in Sources */, - 947162383483B6391F8CDF38249BFBD2 /* CwlCatchException.m in Sources */, - F4A1B7A059AAA6727EB70E58E09332A4 /* CwlCatchException.swift in Sources */, - BB10A2D0B1EE5B1BA811354116F83E3F /* CwlDarwinDefinitions.swift in Sources */, - 86FFB76B2EDCF4AE79CC4C0BD8A0FE9A /* DSL+Wait.swift in Sources */, - 1C7CA1FAFBF8B865596C739FEA39CDEE /* DSL.m in Sources */, - 17261E344C2027602431A636759AC7F2 /* DSL.swift in Sources */, - 8654571F855691C23B7B8E61B2141944 /* EndWith.swift in Sources */, - BF3AF1D2B46E09E2B3DCC824E6C1F5AF /* Equal.swift in Sources */, - 7F6750C7B1847733370B18C4CBFE32DF /* Errors.swift in Sources */, - CB7558CCDD935C9E82BBF454022ED1D3 /* Expectation.swift in Sources */, - 8015239010C1D642F14C105F8FF8E035 /* Expression.swift in Sources */, - 7D6269A3CFE53C28DAA6B92E8FC017A7 /* FailureMessage.swift in Sources */, - FCFFEB587281358CFF05A65ED9E94C12 /* Functional.swift in Sources */, - CE3FA6AE0944D4AE737F0E57CFF4A615 /* HaveCount.swift in Sources */, - 50B80F12A9BAE302F07F6CF94752F462 /* mach_excServer.c in Sources */, - A91166D0A5E8F1D5D5377622C381C045 /* Match.swift in Sources */, - B9BD565DAB07F8E2288A960A1D3EFAC1 /* MatcherFunc.swift in Sources */, - 23E2E1E02FE79EE1E1688CBBAA777297 /* MatcherProtocols.swift in Sources */, - CE4CEF6328E255B380E2B2692B351CF8 /* MatchError.swift in Sources */, - 9E95D6E15DBE9B0FC92AAF60D42D1464 /* Nimble-dummy.m in Sources */, - F9D61EB5EEB799105913685722FF4C9C /* NimbleEnvironment.swift in Sources */, - E5CCEF0B83F8272D10671C01AAE4FFA0 /* NimbleXCTestHandler.swift in Sources */, - DC32331BE565888E694E1321BB1D80F5 /* NMBExceptionCapture.m in Sources */, - 8C30EAD5FFD28B387099B41C74657A67 /* NMBExpectation.swift in Sources */, - AC0B24EF198E3BEDFCC9F25D7B8EEDAB /* NMBObjCMatcher.swift in Sources */, - 127CD37052B8E0BC645D83D4664F59D4 /* NMBStringify.m in Sources */, - EBA52C16F42E42A1824D87C284F4A60C /* PostNotification.swift in Sources */, - 4F3F103945CC52D0A3B8A891BB0E21C4 /* RaisesException.swift in Sources */, - 62744EF299751FB49B5FCD81D8C8FFF7 /* SatisfyAnyOf.swift in Sources */, - 234BFC45ACAC4A8FB945EA17B6A74B0B /* SourceLocation.swift in Sources */, - 9BEBD1791C233763A8DC13080BFB99C9 /* Stringers.swift in Sources */, - 110A640A9BE45841BA938B4C29EF5446 /* ThrowAssertion.swift in Sources */, - 22C1DE74D494C10BBE727F239A68447D /* ThrowError.swift in Sources */, - D88575ED37BC462E8130CDBEFE9EA308 /* XCTestObservationCenter+Register.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5820458A2A51811763E6C69788202609 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BEF9C3C58FEBBAAFC6640C532864F568 /* Action.swift in Sources */, - 5702A743E24EF86F57C079C53994AB8D /* Atomic.swift in Sources */, - 4BD582A689CB31F53ADAF1C676E9608F /* Bag.swift in Sources */, - 75A9698B3E524A3AE1366AFB798A64E4 /* Deprecations+Removals.swift in Sources */, - 4D71AED5656A253602B5F29929E906DB /* Disposable.swift in Sources */, - F76AECB4FEE9BF37ED8996A9D12C3245 /* Event.swift in Sources */, - 4C3F2133B6F3A58301106A9F79A75ABC /* EventLogger.swift in Sources */, - ED11AA80B871081BE92E7F0B6227C947 /* Flatten.swift in Sources */, - 189050F5E247546A7641BFF083AFBBE3 /* FoundationExtensions.swift in Sources */, - A7E82B461C481EBEAA621278AFDF6101 /* Lifetime.swift in Sources */, - F61FCAACA8730FF6AECC66A0E983D5AB /* Observer.swift in Sources */, - 07158F4EAEED03D1C096A264FFF7F4D3 /* Optional.swift in Sources */, - A0E4E8486CCDEC6710FD4649BFF1B515 /* Property.swift in Sources */, - 6B8D25E891A0511F86A5A37D5570D85A /* Reactive.swift in Sources */, - CE32FEAE90ECCBB0D45FD9C86F3F497A /* ReactiveSwift-dummy.m in Sources */, - A5BFD1D307FC92CE1AFA6D049524D052 /* ResultExtensions.swift in Sources */, - 5FFA9972AFA7207AB186A112CC6B1641 /* Scheduler.swift in Sources */, - 0F62ED582583864D79760F5FA3536E3E /* Signal.swift in Sources */, - D592A43EA0A6661FEDFC543CD918BE4D /* SignalProducer.swift in Sources */, - 599BD31B967ACF5D5E1ABC57E79065E9 /* TupleExtensions.swift in Sources */, - AD07F70DF53E2C820D85F52F7564F001 /* UnidirectionalBinding.swift in Sources */, - 3E66A0BD83BD5BE8D65AFB36D0942A5B /* ValidatingProperty.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 64B2E0B5620423B654DFFE82B57C8C78 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 81CC62CF8A1AD74849A246741DD9A8AE /* Callsite.swift in Sources */, - 3C35ABB55635E4E969C2484133A3B4D2 /* Closures.swift in Sources */, - 0BCEEC65C8DB4F60A0EFD9EB193BB99A /* Configuration.swift in Sources */, - 49D5208D5BADCB6F1C2B5BA95C348E4F /* DSL.swift in Sources */, - B503AF03D73353141FD6E0D8C06451F9 /* ErrorUtility.swift in Sources */, - 1AE1445122691B48ED0D8DB61547E97C /* Example.swift in Sources */, - 82D1F822758EB03CD479943CA30D5A38 /* ExampleGroup.swift in Sources */, - F427D567DA533EBDCFA8B56EFF610FB1 /* ExampleHooks.swift in Sources */, - 1D1164642304C652C09F526994329A84 /* ExampleMetadata.swift in Sources */, - 96C9ACF2F8B533643E5ED7123E4AEF88 /* Filter.swift in Sources */, - 2B349866D9AAFD37E568AD026CD88B91 /* HooksPhase.swift in Sources */, - 3CFE5F78A202A2878B8608C9869ED7DB /* NSBundle+CurrentTestBundle.swift in Sources */, - 68B5ABB6BDACDAB1E40F37BFF234B2EA /* NSString+QCKSelectorName.m in Sources */, - 128EC9B7A22F98C84D1ED77021E59862 /* QCKDSL.m in Sources */, - BB81CE2D910A8A5099C430B1C6F5BC7D /* Quick-dummy.m in Sources */, - 229D61E83268F1981C491E27FA4429DD /* QuickConfiguration.m in Sources */, - B7F38094C20E5202546D12EF5DC5BA64 /* QuickSelectedTestSuiteBuilder.swift in Sources */, - 0587E9945FE0EA064A7552DB9D34A98E /* QuickSpec.m in Sources */, - 6FED3CF3C073928BBAFD13BE61270D6D /* QuickTestSuite.swift in Sources */, - 973A4BEBA2ED6C185DC98EA2E2EEF01B /* String+FileName.swift in Sources */, - D6043A4050187335511987CA83C576BD /* SuiteHooks.swift in Sources */, - 7476842145151214CB47BFF8EB617702 /* World+DSL.swift in Sources */, - 760BAF96082DD5B6A743284629EC3308 /* World.swift in Sources */, - 730AE4DFA1C9E6C98D5E9FB3AFA48821 /* XCTestSuite+QuickTestSuiteBuilder.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7A5E66E0250085CFF8C957AF18C0D222 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 57388C6C2B3C17F76EA25EA39EE42B6F /* Reachability-dummy.m in Sources */, - 6F7010E2A68AF250CB9432AF99700979 /* Reachability.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 82131165B4533445C05EC8166BA4EA53 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7726D1D45318323E9B1412DF0F5C9D37 /* CocoaAction.swift in Sources */, - 642C154875522E8ABAA04FB28C6CB1BC /* CocoaTarget.swift in Sources */, - 1D04712344F8AFBC84FB2FC413198ED6 /* DelegateProxy.swift in Sources */, - E3500BC64541901292BF37F9FDF7F503 /* Deprecations+Removals.swift in Sources */, - 16DCB2F5C3B506867F812C6113E41144 /* DynamicProperty.swift in Sources */, - DFEA6137784B39F884FF87F2E6B7BC9D /* MKMapView.swift in Sources */, - 8D1CF1C8C947F820AAFFC6FCC5E3A641 /* NSLayoutConstraint.swift in Sources */, - 41FF3B3A5D18846BD250B1D075DC0764 /* NSObject+Association.swift in Sources */, - 5CDD399EB240116080FD072259A77F01 /* NSObject+BindingTarget.swift in Sources */, - FA0A6F9E0A66709A35DD40296E9C5BF8 /* NSObject+Intercepting.swift in Sources */, - 7A59C0B01342E690DAA6A63054D5B1FA /* NSObject+KeyValueObserving.swift in Sources */, - 945B452BF9ADFE70921027D1160F1484 /* NSObject+Lifetime.swift in Sources */, - B871DFB0E5946358638D39DEF7C0BBBE /* NSObject+ObjCRuntime.swift in Sources */, - 0B15A1CAD338D37362D14D12EAF89CB4 /* NSObject+ReactiveExtensionsProvider.swift in Sources */, - 4391EE2ECE3BA2786D86DA86C00C2AF8 /* NSObject+Synchronizing.swift in Sources */, - 35B1B0B2781D07903BFEA1C0A76F2302 /* ObjC+Constants.swift in Sources */, - 0E294C5A0EFD02EC307BD1D6EE73115B /* ObjC+Messages.swift in Sources */, - 72EB734BAA053E4F3A2830445325CA18 /* ObjC+Runtime.swift in Sources */, - 465A6D3A81AF9DF432D879D5813EBB13 /* ObjC+RuntimeSubclassing.swift in Sources */, - D5CE2FB299B0649CDE47146A0FC50CEB /* ObjC+Selector.swift in Sources */, - 0511654D6963427A5830D45DACFE6064 /* ObjCRuntimeAliases.m in Sources */, - 3E99E7B06D279EA29C8F504614FC6072 /* ReactiveCocoa-dummy.m in Sources */, - 95EB0825E03A9821C7F55903F9F29273 /* ReusableComponents.swift in Sources */, - D123B004D9CE2F73F9634ED353BF73D1 /* UIActivityIndicatorView.swift in Sources */, - 5EF329BF99862C62938AB788669BE8AF /* UIBarButtonItem.swift in Sources */, - 77482810CAF896DC6876023C1362122E /* UIBarItem.swift in Sources */, - B28A0FCD25DED5AA0B68E305638F5BA9 /* UIButton.swift in Sources */, - D57D490D0D836258B35BA8A23485D2A9 /* UICollectionView.swift in Sources */, - ABA98ABBFCF699BE733946CB737CE6B9 /* UIControl.swift in Sources */, - 92AA67627EDA0B84C60D259D54C7ED60 /* UIDatePicker.swift in Sources */, - 16F1E7F21615E00D010072C8F54DE3A1 /* UIGestureRecognizer.swift in Sources */, - A7581CA42D2413F98AF248137A827AA8 /* UIImageView.swift in Sources */, - 632CF89DA882625AEB0F3A7EAB7F1653 /* UIKeyboard.swift in Sources */, - 88908549852319C0587D5DC59ABF542F /* UILabel.swift in Sources */, - 3EE13A63F8E9ED7CFDB83235D6BAD4AC /* UIPickerView.swift in Sources */, - 1CB81E6E538AD7ABC22241F8C8847AE4 /* UIProgressView.swift in Sources */, - 821321102B29CAA5C96FE391283425FB /* UIRefreshControl.swift in Sources */, - 70A80DDEE055E28E0C3D4E1EBC53305E /* UIScrollView.swift in Sources */, - FB04F3F241FDB88DBBBAE98321C664C4 /* UISearchBar.swift in Sources */, - B143EEE4F93C26829429C443540BF4D3 /* UISegmentedControl.swift in Sources */, - D986A3D28BC280B3A90CA9F06762338D /* UISlider.swift in Sources */, - 1E1C5FF6738CEB5F32C403EFAB295065 /* UIStepper.swift in Sources */, - 2BC0D6FA54DD74A454031FEDEC31BC60 /* UISwitch.swift in Sources */, - 81250C24C643652A242941C6904077B3 /* UITableView.swift in Sources */, - 526108C6389FA50A8FDC228DFD8D0A47 /* UITextField.swift in Sources */, - E3A69E75DD947FDCF2FFD3E6832DE80D /* UITextView.swift in Sources */, - CFE009BB73AE7293B985BC0CDF383C17 /* UIView.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 86F290CEB84F7D8700982794E92D0A2A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D52275A90F68E5056410E02CDCF7A56 /* Result-dummy.m in Sources */, - 04766050A11C6E86D5C2762A7283DB1F /* Result.swift in Sources */, - 24445E61E879CF9258A59A745939A35D /* ResultProtocol.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8E138038DA4E1473DF279EEBD6771818 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A5C0A3DF28C2B95FBA5F212D202817E3 /* Aliases.swift in Sources */, - 955E681529AFEA62705D90C06B60ABC9 /* Error.swift in Sources */, - A2F1066AA4D39EEA9EF3D52BE178549B /* LinkingObjects.swift in Sources */, - EC385AF793862383430508BE0072131F /* List.swift in Sources */, - 3BA394A5178E534D4C9CD9325A3F862C /* Migration.swift in Sources */, - 57CAC2857F0D32AE17917EDC5B218CFD /* Object.swift in Sources */, - 78402B1C5038AE832D93BF4C3B56766F /* ObjectiveCSupport.swift in Sources */, - 1572B541D2F6CA85B39FEEC1F633287B /* ObjectSchema.swift in Sources */, - DC420EAA63E76A8DC77AB16713784AAF /* Optional.swift in Sources */, - AC985DC0886CF01DD5FE23F6C5A5A316 /* Property.swift in Sources */, - 5870697EACB3585E86BCF13330B093FD /* Realm.swift in Sources */, - E35405BCC79C15E4591DE81047BAFD54 /* RealmCollection.swift in Sources */, - F3B615FFC3A13BF34DC81A0317BEBE31 /* RealmConfiguration.swift in Sources */, - 6697CB49966B6CB66C382EFEDBE664D8 /* RealmSwift-dummy.m in Sources */, - 7CF1C8A268B9FB75788C1A2E42FDDD87 /* Results.swift in Sources */, - FE9D756C4D34F0A837D5B62670C54BBE /* Schema.swift in Sources */, - 3C3A1BEC07B413F36E7438CB932379F0 /* SortDescriptor.swift in Sources */, - 3548E948AEF451B2F781CCD0D199503E /* SwiftVersion.swift in Sources */, - 348354BC0AA067669E3F51E032DA8469 /* Sync.swift in Sources */, - 294038CA8C05DBD13E34F40A0669815D /* Util.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9C703F3EC1885D7A72CDA26B517AF2EC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2871AFC5EFBA6ED866C11164DAA12A62 /* Error.swift in Sources */, - 9619734C9DEDC0A052C29C9290ABEED5 /* JSON.swift in Sources */, - 9873E590CEB5A8C377F67E455852F0CC /* KeyType.swift in Sources */, - 6EA2E0EB06FEA7B3B78DCF8703E5BBC6 /* Marshal-dummy.m in Sources */, - 1A35C22776FBFD302E2325C331066FE8 /* MarshalDictionary.swift in Sources */, - 1BC29B0D30BA334F7966E56D0415A3DA /* MarshaledObject.swift in Sources */, - E922F348FD0F1B83ABCB3F2E504FE9DA /* Marshaling.swift in Sources */, - D32FDDC568FBE1D35CC4874A89119842 /* Migration.swift in Sources */, - 6AE97685B60446A4640646D889EE099C /* Operators.swift in Sources */, - 3424901DFFB13F114782634415ED1E45 /* Unmarshaling.swift in Sources */, - 5B4BC0368196FADEE78A134EFB3717FF /* UnmarshalingWithContext.swift in Sources */, - A8AC0FCECBBD879B6D59D1D151F16F46 /* UnmarshalUpdating.swift in Sources */, - 414FF843979F8BD7EC6A8317420B3557 /* ValueType.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AE45CD351DEBDD9F2DAE65FF8D523688 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BD8449C1DB198C15FACCCA745AF36D92 /* NSData+ImageContentType.m in Sources */, - 0B708B9ABAC97D45FB17A994F35BADE6 /* NSImage+WebCache.m in Sources */, - A0B7FD0173B14EF31E5C16CB311128FC /* SDImageCache.m in Sources */, - 7940DF18814F9321178EC538E43BA409 /* SDImageCacheConfig.m in Sources */, - 4184EA6C9F7A5553278813C127F51795 /* SDWebImage-dummy.m in Sources */, - 54E5A7DF676BB926250CABA6CB61CA6A /* SDWebImageCompat.m in Sources */, - 98080D71E255BAF41B14B5147F715D17 /* SDWebImageDecoder.m in Sources */, - D4AAF2FE4030CF1DD1BA5F9F80F5A1E1 /* SDWebImageDownloader.m in Sources */, - F0B3BF5F2834AF5BFB44A2466DBEC6B5 /* SDWebImageDownloaderOperation.m in Sources */, - E941A5BA1BB185722A1EC12563319957 /* SDWebImageManager.m in Sources */, - 40F6622927E23BBD26FABDD3E7108480 /* SDWebImagePrefetcher.m in Sources */, - CE1C31CE57468C2E05474E1FFF3935A4 /* UIButton+WebCache.m in Sources */, - C6037A0DB77BF50C4C4C2BA7927DCDDA /* UIImage+GIF.m in Sources */, - D7C51ACAD71B7C2F4474038108BAE033 /* UIImage+MultiFormat.m in Sources */, - 74147EAF25F637C65E7E35965E1F5EA7 /* UIImageView+HighlightedWebCache.m in Sources */, - 2F71D099122CBEF95A180D0C20918DBB /* UIImageView+WebCache.m in Sources */, - DAC615B84E1D443E451B2A98E9801950 /* UIView+WebCache.m in Sources */, - 508B92FDF4F2433D03CA6CFF5F0CF8E1 /* UIView+WebCacheOperation.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B451CA9BFD8C4AAF3103E72BB62918C4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6A9B5F2E706D55A69C6A5E2754A97B2C /* Alternative.swift in Sources */, - 5ACF7DF166DDDA521C5905D11EFB19E6 /* Applicative.swift in Sources */, - 72FF59DB723E0F2E89396B5A9687F045 /* Argo-dummy.m in Sources */, - BDDE3C6B36C7A4390AFF01C125D87A27 /* Argo.swift in Sources */, - 0F0BB306CA857876353E208376BCD352 /* catDecoded.swift in Sources */, - 88F7FB6C300DF156A17FD60E4DFE52B4 /* Decodable.swift in Sources */, - C9C828040F3DBE5B0A5025B14E707C00 /* decode.swift in Sources */, - 424AD01825E6B0836BB7EB22C5D023C7 /* Decoded.swift in Sources */, - 6BC45F532D80B5E2CA7994DAC5F991E1 /* DecodeError.swift in Sources */, - 9B61BFAB089A491FD59D6FDD4A716F14 /* DecodeOperators.swift in Sources */, - 0D0A84C74D45C19FECD0B6185DC37F6D /* Dictionary.swift in Sources */, - E74D73C43866201F2DD30F5FCB640A1C /* FailureCoalescing.swift in Sources */, - 69CCDEC9F7B1E7077F24A57310AEB40F /* flatReduce.swift in Sources */, - 7810F7BA08E09A3CBA4ACA5B752E8627 /* Functor.swift in Sources */, - 49F1E2D496CDB97D6149B190BF1E711D /* JSON.swift in Sources */, - D8B652781696C5589246426D45B4927F /* Monad.swift in Sources */, - 7B957962DCE07FF50BA1011DE56C727B /* NSNumber.swift in Sources */, - AC638215CCCC7AE76B73DFD0AF915859 /* RawRepresentable.swift in Sources */, - 2969819001B203B84C76FB719B7CA2F7 /* sequence.swift in Sources */, - 6007DADE9D72350EEDDCC3C826D27698 /* StandardTypes.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C5EFE7D8EADC33B56144700290EF7ED9 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C4FC16D9DD995BBF6F7B0E5F3DD31FCB /* Pods-ACKReactiveExtensions_Example-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E33FAC6F70FB7A125F4B4878336CF34D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 54436A6669617C2D975F8917FFE99E2C /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 0663AF9F998396D80936468DB167EA31 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Realm; - target = B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */; - targetProxy = 268F06059105B11F6A19C7F0679FC51A /* PBXContainerItemProxy */; - }; - 096C8A380708FE06DC8EB7969AF085B2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ACKReactiveExtensions; - target = DE3EBDE84D7632BA2C58988A7A5C141B /* ACKReactiveExtensions */; - targetProxy = 868623CB91EED714AE22B5BE7019EF20 /* PBXContainerItemProxy */; - }; - 1AAE113CFDF84651E8C611CFEC0F7EAB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SDWebImage; - target = 540B755C72E99D2B6A76D13262796807 /* SDWebImage */; - targetProxy = 8091F6A1327D78C8C10D62251E2510DF /* PBXContainerItemProxy */; - }; - 2070A6E4F49595A4A506F0AC4A526970 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Result; - target = 8107DB93200934B6DEFD700F43910AC7 /* Result */; - targetProxy = A9EB70C31D66DCC3ED09E412F72CD09F /* PBXContainerItemProxy */; - }; - 255CE31E43151486D601CFB1AD21E229 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Marshal; - target = D6A1B9EB7A50D88E5565BEFC1946E68B /* Marshal */; - targetProxy = C36D1D094529C4D7F4339B028399C99C /* PBXContainerItemProxy */; - }; - 2903774E749981E693E3E2FC63AAF836 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Runes; - target = 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */; - targetProxy = 6EBCE95BB06D9C588FAD46C8EBA294C2 /* PBXContainerItemProxy */; - }; - 314E6C2DF88E43F1047E472C10EC0C0A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Runes; - target = 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */; - targetProxy = AFD595F6FDE15902D45F069F4C458AC6 /* PBXContainerItemProxy */; - }; - 35E4B04E4BDB0F2B51DC68DE0FF35263 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Nimble; - target = 1321E318D10CFDC9F5B93A7952492CCD /* Nimble */; - targetProxy = C1C6665408CE50FC216823264320A845 /* PBXContainerItemProxy */; - }; - 3AB4D72A2818CA460ADCF1418EB8A015 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveSwift; - target = F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */; - targetProxy = 022F2C53878C86B427D49C3F9A3F3B42 /* PBXContainerItemProxy */; - }; - 415A95FFA808E41A6FE70F2C0F1B6E36 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Marshal; - target = D6A1B9EB7A50D88E5565BEFC1946E68B /* Marshal */; - targetProxy = 6210B71103B7F90F828D2B87B34142F1 /* PBXContainerItemProxy */; - }; - 507A2518C2065B74C9998C50DFDA914C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Result; - target = 8107DB93200934B6DEFD700F43910AC7 /* Result */; - targetProxy = E55B8EBE25B8676FE9343EBD6AD358D1 /* PBXContainerItemProxy */; - }; - 511AAA384CAF9DD984D69859AB9FCB45 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SDWebImage; - target = 540B755C72E99D2B6A76D13262796807 /* SDWebImage */; - targetProxy = 417783C84CE41C58CD2E25AEF053BCCD /* PBXContainerItemProxy */; - }; - 52373DE9E9033CF7B36AF50C66BCB31D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveCocoa; - target = 5E29F3F45BD6B823A2EC56ECA2397070 /* ReactiveCocoa */; - targetProxy = 5A4C7A8D7284158723FD02FD72F00B39 /* PBXContainerItemProxy */; - }; - 5330A14AF002FBE9CA544949536BC9ED /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Curry; - target = 378E1575B1A77DB0CC90AD1E5B4E59B9 /* Curry */; - targetProxy = FFB5EEA82BFF4012ED49686CC1679DF2 /* PBXContainerItemProxy */; - }; - 62665E4894AD8D03F1AA333A8C245929 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = RealmSwift; - target = 8C3D90B09D20CB4C804DD2F29D525C27 /* RealmSwift */; - targetProxy = EAA9CB03B2D6C959FB38608F9FABC3AB /* PBXContainerItemProxy */; - }; - 6C3A29D21310618A80EC41503A83EE39 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = RealmSwift; - target = 8C3D90B09D20CB4C804DD2F29D525C27 /* RealmSwift */; - targetProxy = DCC7FC76106F1AEC1288E08AA2B978DB /* PBXContainerItemProxy */; - }; - 7B9587C3152AA4572E6887D9D893F16C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Reachability; - target = 3E12B2B47078F77F5CB8A10C0EF8C1AF /* Reachability */; - targetProxy = 8551F1078176927D36C6EDDF4596B1E8 /* PBXContainerItemProxy */; - }; - 7E55C0EEDDDF83B1AB6C9CA15E2395E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Result; - target = 8107DB93200934B6DEFD700F43910AC7 /* Result */; - targetProxy = 394E0F163CF3B2834941FC5B067331DF /* PBXContainerItemProxy */; - }; - 831962E00E58B35F0A3BAAC465B79C0B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Realm; - target = B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */; - targetProxy = 1167D2DE6A16514175322EE736D83EE8 /* PBXContainerItemProxy */; - }; - 85D36FAC3C69573AA831A22A7CF98712 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Result; - target = 8107DB93200934B6DEFD700F43910AC7 /* Result */; - targetProxy = 0A564D03D6479A675AFBE689013DC63C /* PBXContainerItemProxy */; - }; - 8CCE78DF4DC4E388382FBBE35D8D1868 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Argo; - target = 3DE0C97A2313CC9DA982FBC2C12E6B42 /* Argo */; - targetProxy = 62DA32FF9205D947E5D37231C7726BAB /* PBXContainerItemProxy */; - }; - 8FA4D696E27722E08FFBE5D18D431486 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SDWebImage; - target = 540B755C72E99D2B6A76D13262796807 /* SDWebImage */; - targetProxy = 939ECA5E7E12D9730CCDDF264267E9B4 /* PBXContainerItemProxy */; - }; - 9C7F0AA9AE279CB4B692340981CC0190 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = RealmSwift; - target = 8C3D90B09D20CB4C804DD2F29D525C27 /* RealmSwift */; - targetProxy = B4DCEAB745F20AE0FB56B3DB6A35235E /* PBXContainerItemProxy */; - }; - A01DB47DA295C7BB960691F89DBAF339 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveCocoa; - target = 5E29F3F45BD6B823A2EC56ECA2397070 /* ReactiveCocoa */; - targetProxy = C65F8FECD9E4F74DB9E21B1C56C2A140 /* PBXContainerItemProxy */; - }; - A45174844D91D0284691BCAC49AD6AF7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Reachability; - target = 3E12B2B47078F77F5CB8A10C0EF8C1AF /* Reachability */; - targetProxy = C557DDCD838ACA25676D02354BE3C7B2 /* PBXContainerItemProxy */; - }; - A64370BD01242D6B54FBD5549385BD47 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Reachability; - target = 3E12B2B47078F77F5CB8A10C0EF8C1AF /* Reachability */; - targetProxy = 6CDCE1EEACE7899769F18927F4111DE9 /* PBXContainerItemProxy */; - }; - AC396207E9FBF23ABB13EF8E0D8BF1EE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Realm; - target = B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */; - targetProxy = 71F48D6AFD4DCEE19FD35D4D39F85499 /* PBXContainerItemProxy */; - }; - C0ADDD5CA888FC44E5ECE93CC27AC0A1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Runes; - target = 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */; - targetProxy = F95C7236AE93166C9F763DF2C9A2738F /* PBXContainerItemProxy */; - }; - CC7C13C25A80D4978A348698E7B1FBAF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveSwift; - target = F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */; - targetProxy = 02A5AB4173D4402D58F8C21847227712 /* PBXContainerItemProxy */; - }; - CEE94527EBCE1C929CDACB99A21E0835 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Argo; - target = 3DE0C97A2313CC9DA982FBC2C12E6B42 /* Argo */; - targetProxy = A163D67065A494CC460A62DDA52ECAA9 /* PBXContainerItemProxy */; - }; - D24EA64D3844E8BE5A178431D29E7CBD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Marshal; - target = D6A1B9EB7A50D88E5565BEFC1946E68B /* Marshal */; - targetProxy = 4A80235A77DA5B5B48FCBEF03BF7DEFC /* PBXContainerItemProxy */; - }; - E136F29D457F34E5132C03A47AA3D2EB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveSwift; - target = F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */; - targetProxy = B1C9F8CA435D6E088C485E8726B78F07 /* PBXContainerItemProxy */; - }; - EC07B45B6D75D458A3BDDB4D52A3F385 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Realm; - target = B3817DFA9BAAAB53C9A56A08FE0387CA /* Realm */; - targetProxy = 2C898CE5E8147B2BD048279BE6C7317B /* PBXContainerItemProxy */; - }; - EC5F98D1CD047EAF59CE522033432FC4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveCocoa; - target = 5E29F3F45BD6B823A2EC56ECA2397070 /* ReactiveCocoa */; - targetProxy = 33E82E5C3635B42630BFFA63C9EC6C0B /* PBXContainerItemProxy */; - }; - EEDB4A7EF92F037CDD37AC16274C47C0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Result; - target = 8107DB93200934B6DEFD700F43910AC7 /* Result */; - targetProxy = B35FE5201D658D1C8DA0FDFEA34456A0 /* PBXContainerItemProxy */; - }; - F24610420965E1A62753ED451581EE44 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Argo; - target = 3DE0C97A2313CC9DA982FBC2C12E6B42 /* Argo */; - targetProxy = FDD249EAA8F66FD9AE57489AADD87277 /* PBXContainerItemProxy */; - }; - F860A32EAE85A201262D45B6A286762C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ReactiveSwift; - target = F01F6ACDF071C28A104A302C201DFFD2 /* ReactiveSwift */; - targetProxy = 98CB46E129F42EF1B9E86F530C41C0C1 /* PBXContainerItemProxy */; - }; - F8EA201877886AD848505482C7F0E6A2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Runes; - target = 5E4CE6EDCFC306EAF6969FB5567CF4AD /* Runes */; - targetProxy = 6184E1225CF5815F75CA581A380FFD51 /* PBXContainerItemProxy */; - }; - F905316CAE5764F3CAB887E9F812F8DD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ACKReactiveExtensions; - target = DE3EBDE84D7632BA2C58988A7A5C141B /* ACKReactiveExtensions */; - targetProxy = 2564FDF9181BB0A672BDFA61DCA33F56 /* PBXContainerItemProxy */; - }; - F94E8763881C765715E69B08A94380C4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Quick; - target = 96D93470C408341136D1AE696D2459E6 /* Quick */; - targetProxy = 5BD206E940F70B7E7AE6A909BC2C61F8 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 04020B9E0797A7C9CA7A101EA9312572 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A39C238E75ECD4C8358AF6078BEEF931 /* Nimble.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Nimble/Nimble-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Nimble/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Nimble/Nimble.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Nimble; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 146CC2F93C41AC4F13FD97F11FED93D3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8BAEF129B05502833A3C38D1187D1F7B /* Reachability.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Reachability/Reachability-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Reachability/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Reachability/Reachability.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Reachability; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 25EB2076B2AB6BBD74517923A5233197 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B1D795BFC1FB929416B4C0C3D2D66E5C /* Argo.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Argo/Argo-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Argo/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Argo/Argo.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Argo; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 272634A181E0DBD5B04E23FFCA53D982 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 02C78CD73F93EA8B253C2061F339748D /* Quick.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Quick/Quick-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Quick/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Quick/Quick.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Quick; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 4325B12F7D7DC571B081C33847219AFC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F2003DAC1567552EAFAC7EDB58AACEF0 /* Marshal.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Marshal/Marshal-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Marshal/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Marshal/Marshal.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Marshal; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 43B24966F04B3FDCDEE196CD4A5B6662 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3CA2661FAA5D698D8172B937E805E9D0 /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 4D9023BCE7F7AF6792F25E15CFE227C4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8B7379B6BEAA2C66A9A218110F722599 /* Curry.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Curry/Curry-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Curry/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Curry/Curry.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Curry; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 50D6875E9980E88525ECEE0D51EF4153 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8BAEF129B05502833A3C38D1187D1F7B /* Reachability.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Reachability/Reachability-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Reachability/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Reachability/Reachability.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Reachability; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 5837DF4B1BF4A66AC01CC25998A54FB8 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8B7379B6BEAA2C66A9A218110F722599 /* Curry.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Curry/Curry-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Curry/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Curry/Curry.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Curry; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 58D4FC77803049CE736D46C6DFCA5BE9 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33BC9D10BB8C5D4C51A61305E606E8E4 /* SDWebImage.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/SDWebImage/SDWebImage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SDWebImage/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SDWebImage/SDWebImage.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = SDWebImage; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 632DF324E3C22B31D0A3C3850A67DBB6 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5A084AD5E025AAF2890332298FD0D304 /* ReactiveCocoa.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ReactiveCocoa/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = ReactiveCocoa; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 65A1D6512F9537B32738B305888CBE98 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6182E9EC62179AFCE72E2ED9B9E2F0D9 /* ReactiveSwift.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ReactiveSwift/ReactiveSwift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ReactiveSwift/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ReactiveSwift/ReactiveSwift.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = ReactiveSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 6B33F3798442EF00B31A08AF10029178 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F2003DAC1567552EAFAC7EDB58AACEF0 /* Marshal.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Marshal/Marshal-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Marshal/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Marshal/Marshal.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Marshal; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 6E762EB93F7526DB58977B06A4CDB9CA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2920E42C255817A6E40496468D7DCC7D /* Realm.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Realm/Realm-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Realm/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Realm/Realm.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Realm; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 7A0127A7A82AC1AF12FE077AD1CA1D28 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F389872021366FA1398C0313163136D3 /* RealmSwift.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/RealmSwift/RealmSwift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/RealmSwift/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/RealmSwift/RealmSwift.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = RealmSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 7FC274687E6AA771F9AAC7290FD5FFFC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A8FE40626F29606EE28AF5449B7B14CD /* ACKReactiveExtensions.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ACKReactiveExtensions/ACKReactiveExtensions-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ACKReactiveExtensions/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ACKReactiveExtensions/ACKReactiveExtensions.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = ACKReactiveExtensions; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 89F6FE25646A160810A5FE43306D21B7 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B99B990B81693D607321364CAD6D517D /* Pods-ACKReactiveExtensions_Example.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example/Pods-ACKReactiveExtensions_Example.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ACKReactiveExtensions_Example; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 8DED8AD26D381A6ACFF202E5217EC498 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 907070E1089E9782626A232E57139D0C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A8FE40626F29606EE28AF5449B7B14CD /* ACKReactiveExtensions.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ACKReactiveExtensions/ACKReactiveExtensions-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ACKReactiveExtensions/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ACKReactiveExtensions/ACKReactiveExtensions.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = ACKReactiveExtensions; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 967F233925DF5A82F1D9785265F6B0B5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2718B96AF1AF5798736F5F61B15D2262 /* Pods-ACKReactiveExtensions_Example.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example/Pods-ACKReactiveExtensions_Example.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ACKReactiveExtensions_Example; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 97E4927753999891677F36313014F8DC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C12F0313F515579E91389CB53B065D1 /* Runes.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Runes/Runes-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Runes/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Runes/Runes.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Runes; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 9B8377E46F0A28AB7B62A5C06949F5A4 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2920E42C255817A6E40496468D7DCC7D /* Realm.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Realm/Realm-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Realm/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Realm/Realm.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Realm; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 9E1E4E48AF2EAB23169E611BF694090A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = NO; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - ONLY_ACTIVE_ARCH = YES; - PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 9FC0F6F76EB18031326041EBC6FD351E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CCC0CA1E4D7FCB37BB43C06596770A3C /* Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests/Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ACKReactiveExtensions_Example_ACKReactiveExtensions_Tests; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - A1B59397E44090282209A3421457A6BC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C12F0313F515579E91389CB53B065D1 /* Runes.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Runes/Runes-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Runes/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Runes/Runes.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Runes; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - B744CB0D195A94205800759DAC2AEB1F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 02C78CD73F93EA8B253C2061F339748D /* Quick.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Quick/Quick-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Quick/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Quick/Quick.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Quick; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - BAB07BA4D8D5EF32BB7217C3DC2386C5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F389872021366FA1398C0313163136D3 /* RealmSwift.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/RealmSwift/RealmSwift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/RealmSwift/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/RealmSwift/RealmSwift.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = RealmSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - BF594A81DB15DB345BA176E0ACAC35B1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6182E9EC62179AFCE72E2ED9B9E2F0D9 /* ReactiveSwift.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ReactiveSwift/ReactiveSwift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ReactiveSwift/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ReactiveSwift/ReactiveSwift.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = ReactiveSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - C5BEEF000D57AF263CB2BEC13F6806F8 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33BC9D10BB8C5D4C51A61305E606E8E4 /* SDWebImage.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/SDWebImage/SDWebImage-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SDWebImage/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SDWebImage/SDWebImage.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = SDWebImage; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - D7B9076A9C78E18A8605B3758EEE0B71 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A39C238E75ECD4C8358AF6078BEEF931 /* Nimble.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Nimble/Nimble-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Nimble/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Nimble/Nimble.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Nimble; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - DC486EC72655568E721BDDD08D3451A4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B11C4A93148054BB7AC617A782F1B743 /* Result.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Result; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - E3E2965C83E2357458B2CB27ABA8F49C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B11C4A93148054BB7AC617A782F1B743 /* Result.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Result; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - ED35DA7828E2B60D7129C5D9A4A6EBEA /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B1D795BFC1FB929416B4C0C3D2D66E5C /* Argo.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Argo/Argo-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Argo/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Argo/Argo.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Argo; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - FCCFEBC0713FAFBD51C2D5AE1748A3E4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5A084AD5E025AAF2890332298FD0D304 /* ReactiveCocoa.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ReactiveCocoa/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = ReactiveCocoa; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 148A7783D63EAB41DFDBC1895EDFDDE5 /* Build configuration list for PBXNativeTarget "Reachability" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 146CC2F93C41AC4F13FD97F11FED93D3 /* Debug */, - 50D6875E9980E88525ECEE0D51EF4153 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1B163EA84BC35A17D33D319232A9E8D4 /* Build configuration list for PBXNativeTarget "Quick" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 272634A181E0DBD5B04E23FFCA53D982 /* Debug */, - B744CB0D195A94205800759DAC2AEB1F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 254AF3FD9BB6B7CB2327611FF034D70E /* Build configuration list for PBXNativeTarget "SDWebImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C5BEEF000D57AF263CB2BEC13F6806F8 /* Debug */, - 58D4FC77803049CE736D46C6DFCA5BE9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 275AC031F358FD9C1A1945F3B3F45450 /* Build configuration list for PBXNativeTarget "Realm" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6E762EB93F7526DB58977B06A4CDB9CA /* Debug */, - 9B8377E46F0A28AB7B62A5C06949F5A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 29B7D73F2439424DC5BB3EF0CF0065EB /* Build configuration list for PBXNativeTarget "Argo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 25EB2076B2AB6BBD74517923A5233197 /* Debug */, - ED35DA7828E2B60D7129C5D9A4A6EBEA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2CE93F5BC6127A8D006A637C0612EC87 /* Build configuration list for PBXNativeTarget "Runes" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97E4927753999891677F36313014F8DC /* Debug */, - A1B59397E44090282209A3421457A6BC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9E1E4E48AF2EAB23169E611BF694090A /* Debug */, - 8DED8AD26D381A6ACFF202E5217EC498 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4BDA66AD220ABFE08994873139073A67 /* Build configuration list for PBXNativeTarget "ReactiveCocoa" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - FCCFEBC0713FAFBD51C2D5AE1748A3E4 /* Debug */, - 632DF324E3C22B31D0A3C3850A67DBB6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 505E5D5BE85FB65F3CCC3748B677ADB5 /* Build configuration list for PBXNativeTarget "ACKReactiveExtensions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7FC274687E6AA771F9AAC7290FD5FFFC /* Debug */, - 907070E1089E9782626A232E57139D0C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 580701FC11C60A37428C21E5E6CD40D5 /* Build configuration list for PBXNativeTarget "Marshal" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6B33F3798442EF00B31A08AF10029178 /* Debug */, - 4325B12F7D7DC571B081C33847219AFC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 64C97413B9489AAF9EE36465E0C164BF /* Build configuration list for PBXNativeTarget "ReactiveSwift" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BF594A81DB15DB345BA176E0ACAC35B1 /* Debug */, - 65A1D6512F9537B32738B305888CBE98 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9980AE4F9112C78250AE09BFD6E89A9B /* Build configuration list for PBXNativeTarget "Pods-ACKReactiveExtensions_Example-ACKReactiveExtensions_Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 43B24966F04B3FDCDEE196CD4A5B6662 /* Debug */, - 9FC0F6F76EB18031326041EBC6FD351E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 99FCB002E66D63F1F7B5E45F9E9675CB /* Build configuration list for PBXNativeTarget "Pods-ACKReactiveExtensions_Example" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 89F6FE25646A160810A5FE43306D21B7 /* Debug */, - 967F233925DF5A82F1D9785265F6B0B5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B0BEB80584AD389708E7629F1320AEF8 /* Build configuration list for PBXNativeTarget "Result" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DC486EC72655568E721BDDD08D3451A4 /* Debug */, - E3E2965C83E2357458B2CB27ABA8F49C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B1DBAFB75A3AF98C8C6B0863BDC7A2E3 /* Build configuration list for PBXNativeTarget "Nimble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D7B9076A9C78E18A8605B3758EEE0B71 /* Debug */, - 04020B9E0797A7C9CA7A101EA9312572 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D24F5DA1081D06F59DB164D62A62ED35 /* Build configuration list for PBXNativeTarget "RealmSwift" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BAB07BA4D8D5EF32BB7217C3DC2386C5 /* Debug */, - 7A0127A7A82AC1AF12FE077AD1CA1D28 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D3805B445D3E6689AE33CEAB50F7DE9F /* Build configuration list for PBXNativeTarget "Curry" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4D9023BCE7F7AF6792F25E15CFE227C4 /* Debug */, - 5837DF4B1BF4A66AC01CC25998A54FB8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; -} diff --git a/Example/Pods/ReactiveSwift/Sources/Optional.swift b/Example/Pods/ReactiveSwift/Sources/Optional.swift deleted file mode 100644 index c5446bd..0000000 --- a/Example/Pods/ReactiveSwift/Sources/Optional.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Optional.swift -// ReactiveSwift -// -// Created by Neil Pankey on 6/24/15. -// Copyright (c) 2015 GitHub. All rights reserved. -// - -/// An optional protocol for use in type constraints. -public protocol OptionalProtocol { - /// The type contained in the otpional. - associatedtype Wrapped - - init(reconstructing value: Wrapped?) - - /// Extracts an optional from the receiver. - var optional: Wrapped? { get } -} - -extension Optional: OptionalProtocol { - public var optional: Wrapped? { - return self - } - - public init(reconstructing value: Wrapped?) { - self = value - } -} - -extension SignalProtocol { - /// Turns each value into an Optional. - internal func optionalize() -> Signal { - return map(Optional.init) - } -} - -extension SignalProducerProtocol { - /// Turns each value into an Optional. - internal func optionalize() -> SignalProducer { - return lift { $0.optionalize() } - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/Property.swift b/Example/Pods/ReactiveSwift/Sources/Property.swift deleted file mode 100644 index 604ffe2..0000000 --- a/Example/Pods/ReactiveSwift/Sources/Property.swift +++ /dev/null @@ -1,705 +0,0 @@ -import Foundation -import enum Result.NoError - -/// Represents a property that allows observation of its changes. -/// -/// Only classes can conform to this protocol, because having a signal -/// for changes over time implies the origin must have a unique identity. -public protocol PropertyProtocol: class, BindingSource { - associatedtype Value - - /// The current value of the property. - var value: Value { get } - - /// The values producer of the property. - /// - /// It produces a signal that sends the property's current value, - /// followed by all changes over time. It completes when the property - /// has deinitialized, or has no further change. - /// - /// - note: If `self` is a composed property, the producer would be - /// bound to the lifetime of its sources. - var producer: SignalProducer { get } - - /// A signal that will send the property's changes over time. It - /// completes when the property has deinitialized, or has no further - /// change. - /// - /// - note: If `self` is a composed property, the signal would be - /// bound to the lifetime of its sources. - var signal: Signal { get } -} - -extension PropertyProtocol { - @discardableResult - public func observe(_ observer: Observer, during lifetime: Lifetime) -> Disposable? { - return producer.observe(observer, during: lifetime) - } -} - -/// Represents an observable property that can be mutated directly. -public protocol MutablePropertyProtocol: PropertyProtocol, BindingTargetProvider, BindingTargetProtocol { - /// The current value of the property. - var value: Value { get set } - - /// The lifetime of the property. - var lifetime: Lifetime { get } -} - -/// Default implementation of `BindingTargetProvider` for mutable properties. -extension MutablePropertyProtocol { - public var bindingTarget: BindingTarget { - return BindingTarget(lifetime: lifetime) { [weak self] in self?.value = $0 } - } -} - -/// Represents a mutable property that can be safety composed by exposing its -/// synchronization mechanic through the defined closure-based interface. -public protocol ComposableMutablePropertyProtocol: MutablePropertyProtocol { - /// Atomically performs an arbitrary action using the current value of the - /// variable. - /// - /// - parameters: - /// - action: A closure that accepts current property value. - /// - /// - returns: the result of the action. - func withValue(action: (Value) throws -> Result) rethrows -> Result - - /// Atomically modifies the variable. - /// - /// - parameters: - /// - action: A closure that accepts old property value and returns a new - /// property value. - /// - /// - returns: The result of the action. - func modify(_ action: (inout Value) throws -> Result) rethrows -> Result -} - -// Property operators. -// -// A composed property is a transformed view of its sources, and does not -// own its lifetime. Its producer and signal are bound to the lifetime of -// its sources. - -extension PropertyProtocol { - /// Lifts a unary SignalProducer operator to operate upon PropertyProtocol instead. - fileprivate func lift(_ transform: @escaping (SignalProducer) -> SignalProducer) -> Property { - return Property(self, transform: transform) - } - - /// Lifts a binary SignalProducer operator to operate upon PropertyProtocol instead. - fileprivate func lift(_ transform: @escaping (SignalProducer) -> (SignalProducer) -> SignalProducer) -> (P) -> Property { - return { otherProperty in - return Property(self, otherProperty, transform: transform) - } - } - - /// Maps the current value and all subsequent values to a new property. - /// - /// - parameters: - /// - transform: A closure that will map the current `value` of this - /// `Property` to a new value. - /// - /// - returns: A property that holds a mapped value from `self`. - public func map(_ transform: @escaping (Value) -> U) -> Property { - return lift { $0.map(transform) } - } - - /// Combines the current value and the subsequent values of two `Property`s in - /// the manner described by `Signal.combineLatest(with:)`. - /// - /// - parameters: - /// - other: A property to combine `self`'s value with. - /// - /// - returns: A property that holds a tuple containing values of `self` and - /// the given property. - public func combineLatest(with other: P) -> Property<(Value, P.Value)> { - return lift(SignalProducer.combineLatest(with:))(other) - } - - /// Zips the current value and the subsequent values of two `Property`s in - /// the manner described by `Signal.zipWith`. - /// - /// - parameters: - /// - other: A property to zip `self`'s value with. - /// - /// - returns: A property that holds a tuple containing values of `self` and - /// the given property. - public func zip(with other: P) -> Property<(Value, P.Value)> { - return lift(SignalProducer.zip(with:))(other) - } - - /// Forward events from `self` with history: values of the returned property - /// are a tuple whose first member is the previous value and whose second - /// member is the current value. `initial` is supplied as the first member - /// when `self` sends its first value. - /// - /// - parameters: - /// - initial: A value that will be combined with the first value sent by - /// `self`. - /// - /// - returns: A property that holds tuples that contain previous and - /// current values of `self`. - public func combinePrevious(_ initial: Value) -> Property<(Value, Value)> { - return lift { $0.combinePrevious(initial) } - } - - /// Forward only those values from `self` which do not pass `isRepeat` with - /// respect to the previous value. - /// - /// - parameters: - /// - isRepeat: A predicate to determine if the two given values are equal. - /// - /// - returns: A property that does not emit events for two equal values - /// sequentially. - public func skipRepeats(_ isRepeat: @escaping (Value, Value) -> Bool) -> Property { - return lift { $0.skipRepeats(isRepeat) } - } -} - -extension PropertyProtocol where Value: Equatable { - /// Forward only those values from `self` which do not pass `isRepeat` with - /// respect to the previous value. - /// - /// - returns: A property that does not emit events for two equal values - /// sequentially. - public func skipRepeats() -> Property { - return lift { $0.skipRepeats() } - } -} - -extension PropertyProtocol where Value: PropertyProtocol { - /// Flattens the inner property held by `self` (into a single property of - /// values), according to the semantics of the given strategy. - /// - /// - parameters: - /// - strategy: The preferred flatten strategy. - /// - /// - returns: A property that sends the values of its inner properties. - public func flatten(_ strategy: FlattenStrategy) -> Property { - return lift { $0.flatMap(strategy) { $0.producer } } - } -} - -extension PropertyProtocol { - /// Maps each property from `self` to a new property, then flattens the - /// resulting properties (into a single property), according to the - /// semantics of the given strategy. - /// - /// - parameters: - /// - strategy: The preferred flatten strategy. - /// - transform: The transform to be applied on `self` before flattening. - /// - /// - returns: A property that sends the values of its inner properties. - public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> P) -> Property { - return lift { $0.flatMap(strategy) { transform($0).producer } } - } - - /// Forward only those values from `self` that have unique identities across - /// the set of all values that have been held. - /// - /// - note: This causes the identities to be retained to check for - /// uniqueness. - /// - /// - parameters: - /// - transform: A closure that accepts a value and returns identity - /// value. - /// - /// - returns: A property that sends unique values during its lifetime. - public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> Property { - return lift { $0.uniqueValues(transform) } - } -} - -extension PropertyProtocol where Value: Hashable { - /// Forwards only those values from `self` that are unique across the set of - /// all values that have been seen. - /// - /// - note: This causes the identities to be retained to check for uniqueness. - /// Providing a function that returns a unique value for each sent - /// value can help you reduce the memory footprint. - /// - /// - returns: A property that sends unique values during its lifetime. - public func uniqueValues() -> Property { - return lift { $0.uniqueValues() } - } -} - -extension PropertyProtocol { - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B) -> Property<(A.Value, B.Value)> where Value == A.Value { - return a.combineLatest(with: b) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C) -> Property<(A.Value, B.Value, C.Value)> where Value == A.Value { - return combineLatest(a, b) - .combineLatest(with: c) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D) -> Property<(A.Value, B.Value, C.Value, D.Value)> where Value == A.Value { - return combineLatest(a, b, c) - .combineLatest(with: d) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value)> where Value == A.Value { - return combineLatest(a, b, c, d) - .combineLatest(with: e) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value)> where Value == A.Value { - return combineLatest(a, b, c, d, e) - .combineLatest(with: f) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value)> where Value == A.Value { - return combineLatest(a, b, c, d, e, f) - .combineLatest(with: g) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value)> where Value == A.Value { - return combineLatest(a, b, c, d, e, f, g) - .combineLatest(with: h) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value)> where Value == A.Value { - return combineLatest(a, b, c, d, e, f, g, h) - .combineLatest(with: i) - .map(repack) - } - - /// Combines the values of all the given properties, in the manner described - /// by `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value)> where Value == A.Value { - return combineLatest(a, b, c, d, e, f, g, h, i) - .combineLatest(with: j) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. Returns nil if the sequence is empty. - public static func combineLatest(_ properties: S) -> Property<[S.Iterator.Element.Value]>? where S.Iterator.Element: PropertyProtocol { - var generator = properties.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { property, next in - property.combineLatest(with: next).map { $0.0 + [$0.1] } - } - } - - return nil - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B) -> Property<(A.Value, B.Value)> where Value == A.Value { - return a.zip(with: b) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C) -> Property<(A.Value, B.Value, C.Value)> where Value == A.Value { - return zip(a, b) - .zip(with: c) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D) -> Property<(A.Value, B.Value, C.Value, D.Value)> where Value == A.Value { - return zip(a, b, c) - .zip(with: d) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value)> where Value == A.Value { - return zip(a, b, c, d) - .zip(with: e) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value)> where Value == A.Value { - return zip(a, b, c, d, e) - .zip(with: f) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value)> where Value == A.Value { - return zip(a, b, c, d, e, f) - .zip(with: g) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value)> where Value == A.Value { - return zip(a, b, c, d, e, f, g) - .zip(with: h) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value)> where Value == A.Value { - return zip(a, b, c, d, e, f, g, h) - .zip(with: i) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. - public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value)> where Value == A.Value { - return zip(a, b, c, d, e, f, g, h, i) - .zip(with: j) - .map(repack) - } - - /// Zips the values of all the given properties, in the manner described by - /// `zip(with:)`. Returns nil if the sequence is empty. - public static func zip(_ properties: S) -> Property<[S.Iterator.Element.Value]>? where S.Iterator.Element: PropertyProtocol { - var generator = properties.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { property, next in - property.zip(with: next).map { $0.0 + [$0.1] } - } - } - - return nil - } -} - -extension PropertyProtocol where Value == Bool { - /// Create a property that computes a logical NOT in the latest values of `self`. - /// - /// - returns: A property that contains the logial NOT results. - public var negated: Property { - return self.lift { $0.negated } - } - - /// Create a property that computes a logical AND between the latest values of `self` - /// and `property`. - /// - /// - parameters: - /// - property: Property to be combined with `self`. - /// - /// - returns: A property that contains the logial AND results. - public func and(_ property: Property) -> Property { - return self.lift(SignalProducer.and)(property) - } - - /// Create a property that computes a logical OR between the latest values of `self` - /// and `property`. - /// - /// - parameters: - /// - property: Property to be combined with `self`. - /// - /// - returns: A property that contains the logial OR results. - public func or(_ property: Property) -> Property { - return self.lift(SignalProducer.or)(property) - } -} - -/// A read-only property that can be observed for its changes over time. There -/// are three categories of read-only properties: -/// -/// # Constant property -/// Created by `Property(value:)`, the producer and signal of a constant -/// property would complete immediately when it is initialized. -/// -/// # Existential property -/// Created by `Property(capturing:)`, it wraps any arbitrary `PropertyProtocol` -/// types, and passes through the behavior. Note that it would retain the -/// wrapped property. -/// -/// Existential property would be deprecated when generalized existential -/// eventually lands in Swift. -/// -/// # Composed property -/// A composed property presents a composed view of its sources, which can be -/// one or more properties, a producer, or a signal. It can be created using -/// property composition operators, `Property(_:)` or `Property(initial:then:)`. -/// -/// It does not own its lifetime, and its producer and signal are bound to the -/// lifetime of its sources. It also does not have an influence on its sources, -/// so retaining a composed property would not prevent its sources from -/// deinitializing. -/// -/// Note that composed properties do not retain any of its sources. -public final class Property: PropertyProtocol { - private let disposable: Disposable? - - private let _value: () -> Value - private let _producer: () -> SignalProducer - private let _signal: () -> Signal - - /// The current value of the property. - public var value: Value { - return _value() - } - - /// A producer for Signals that will send the property's current - /// value, followed by all changes over time, then complete when the - /// property has deinitialized or has no further changes. - /// - /// - note: If `self` is a composed property, the producer would be - /// bound to the lifetime of its sources. - public var producer: SignalProducer { - return _producer() - } - - /// A signal that will send the property's changes over time, then - /// complete when the property has deinitialized or has no further changes. - /// - /// - note: If `self` is a composed property, the signal would be - /// bound to the lifetime of its sources. - public var signal: Signal { - return _signal() - } - - /// Initializes a constant property. - /// - /// - parameters: - /// - property: A value of the constant property. - public init(value: Value) { - disposable = nil - _value = { value } - _producer = { SignalProducer(value: value) } - _signal = { Signal.empty } - } - - /// Initializes an existential property which wraps the given property. - /// - /// - note: The resulting property retains the given property. - /// - /// - parameters: - /// - property: A property to be wrapped. - public init(capturing property: P) where P.Value == Value { - disposable = nil - _value = { property.value } - _producer = { property.producer } - _signal = { property.signal } - } - - /// Initializes a composed property which reflects the given property. - /// - /// - note: The resulting property does not retain the given property. - /// - /// - parameters: - /// - property: A property to be wrapped. - public convenience init(_ property: P) where P.Value == Value { - self.init(unsafeProducer: property.producer) - } - - /// Initializes a composed property that first takes on `initial`, then each - /// value sent on a signal created by `producer`. - /// - /// - parameters: - /// - initial: Starting value for the property. - /// - values: A producer that will start immediately and send values to - /// the property. - public convenience init(initial: Value, then values: SignalProducer) { - self.init(unsafeProducer: values.prefix(value: initial)) - } - - /// Initialize a composed property that first takes on `initial`, then each - /// value sent on `signal`. - /// - /// - parameters: - /// - initialValue: Starting value for the property. - /// - values: A signal that will send values to the property. - public convenience init(initial: Value, then values: Signal) { - self.init(unsafeProducer: SignalProducer(values).prefix(value: initial)) - } - - /// Initialize a composed property by applying the unary `SignalProducer` - /// transform on `property`. - /// - /// - parameters: - /// - property: The source property. - /// - transform: A unary `SignalProducer` transform to be applied on - /// `property`. - fileprivate convenience init( - _ property: P, - transform: @escaping (SignalProducer) -> SignalProducer - ) { - self.init(unsafeProducer: transform(property.producer)) - } - - /// Initialize a composed property by applying the binary `SignalProducer` - /// transform on `firstProperty` and `secondProperty`. - /// - /// - parameters: - /// - firstProperty: The first source property. - /// - secondProperty: The first source property. - /// - transform: A binary `SignalProducer` transform to be applied on - /// `firstProperty` and `secondProperty`. - fileprivate convenience init(_ firstProperty: P1, _ secondProperty: P2, transform: @escaping (SignalProducer) -> (SignalProducer) -> SignalProducer) { - self.init(unsafeProducer: transform(firstProperty.producer)(secondProperty.producer)) - } - - /// Initialize a composed property from a producer that promises to send - /// at least one value synchronously in its start handler before sending any - /// subsequent event. - /// - /// - important: The producer and the signal of the created property would - /// complete only when the `unsafeProducer` completes. - /// - /// - warning: If the producer fails its promise, a fatal error would be - /// raised. - /// - /// - parameters: - /// - unsafeProducer: The composed producer for creating the property. - private init(unsafeProducer: SignalProducer) { - // Share a replayed producer with `self.producer` and `self.signal` so - // they see a consistent view of the `self.value`. - // https://github.com/ReactiveCocoa/ReactiveCocoa/pull/3042 - let producer = unsafeProducer.replayLazily(upTo: 1) - - let atomic = Atomic(nil) - disposable = producer.startWithValues { atomic.value = $0 } - - // Verify that an initial is sent. This is friendlier than deadlocking - // in the event that one isn't. - guard atomic.value != nil else { - fatalError("A producer promised to send at least one value. Received none.") - } - - _value = { atomic.value! } - _producer = { producer } - _signal = { producer.startAndRetrieveSignal() } - } - - deinit { - disposable?.dispose() - } -} - -/// A mutable property of type `Value` that allows observation of its changes. -/// -/// Instances of this class are thread-safe. -public final class MutableProperty: ComposableMutablePropertyProtocol { - private let token: Lifetime.Token - private let observer: Signal.Observer - private let atomic: RecursiveAtomic - - /// The current value of the property. - /// - /// Setting this to a new value will notify all observers of `signal`, or - /// signals created using `producer`. - public var value: Value { - get { - return atomic.withValue { $0 } - } - - set { - swap(newValue) - } - } - - /// The lifetime of the property. - public let lifetime: Lifetime - - /// A signal that will send the property's changes over time, - /// then complete when the property has deinitialized. - public let signal: Signal - - /// A producer for Signals that will send the property's current value, - /// followed by all changes over time, then complete when the property has - /// deinitialized. - public var producer: SignalProducer { - return SignalProducer { [atomic, weak self] producerObserver, producerDisposable in - atomic.withValue { value in - if let strongSelf = self { - producerObserver.send(value: value) - producerDisposable += strongSelf.signal.observe(producerObserver) - } else { - producerObserver.send(value: value) - producerObserver.sendCompleted() - } - } - } - } - - /// Initializes a mutable property that first takes on `initialValue` - /// - /// - parameters: - /// - initialValue: Starting value for the mutable property. - public init(_ initialValue: Value) { - (signal, observer) = Signal.pipe() - token = Lifetime.Token() - lifetime = Lifetime(token) - - /// Need a recursive lock around `value` to allow recursive access to - /// `value`. Note that recursive sets will still deadlock because the - /// underlying producer prevents sending recursive events. - atomic = RecursiveAtomic(initialValue, - name: "org.reactivecocoa.ReactiveSwift.MutableProperty", - didSet: observer.send(value:)) - } - - /// Atomically replaces the contents of the variable. - /// - /// - parameters: - /// - newValue: New property value. - /// - /// - returns: The previous property value. - @discardableResult - public func swap(_ newValue: Value) -> Value { - return atomic.swap(newValue) - } - - /// Atomically modifies the variable. - /// - /// - parameters: - /// - action: A closure that accepts old property value and returns a new - /// property value. - /// - /// - returns: The result of the action. - @discardableResult - public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { - return try atomic.modify(action) - } - - /// Atomically performs an arbitrary action using the current value of the - /// variable. - /// - /// - parameters: - /// - action: A closure that accepts current property value. - /// - /// - returns: the result of the action. - @discardableResult - public func withValue(action: (Value) throws -> Result) rethrows -> Result { - return try atomic.withValue(action) - } - - deinit { - observer.sendCompleted() - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/Reactive.swift b/Example/Pods/ReactiveSwift/Sources/Reactive.swift deleted file mode 100644 index a1412aa..0000000 --- a/Example/Pods/ReactiveSwift/Sources/Reactive.swift +++ /dev/null @@ -1,33 +0,0 @@ -/// Describes a provider of reactive extensions. -/// -/// - note: `ReactiveExtensionsProvider` does not indicate whether a type is -/// reactive. It is intended for extensions to types that are not owned -/// by the module in order to avoid name collisions and return type -/// ambiguities. -public protocol ReactiveExtensionsProvider: class {} - -extension ReactiveExtensionsProvider { - /// A proxy which hosts reactive extensions for `self`. - public var reactive: Reactive { - return Reactive(self) - } - - /// A proxy which hosts static reactive extensions for the type of `self`. - public static var reactive: Reactive.Type { - return Reactive.self - } -} - -/// A proxy which hosts reactive extensions of `Base`. -public struct Reactive { - /// The `Base` instance the extensions would be invoked with. - public let base: Base - - // Construct a proxy. - // - // - parameters: - // - base: The object to be proxied. - fileprivate init(_ base: Base) { - self.base = base - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/ResultExtensions.swift b/Example/Pods/ReactiveSwift/Sources/ResultExtensions.swift deleted file mode 100644 index c0f7143..0000000 --- a/Example/Pods/ReactiveSwift/Sources/ResultExtensions.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Result - -/// Private alias of the free `materialize()` from `Result`. -/// -/// This exists because within a `Signal` or `SignalProducer` operator, -/// `materialize()` refers to the operator with that name. -/// Namespacing as `Result.materialize()` doesn't work either, -/// because it tries to resolve a static member on the _type_ -/// `Result`, rather than the free function in the _module_ -/// of the same name. -internal func materialize(_ f: () throws -> T) -> Result { - return materialize(try f()) -} diff --git a/Example/Pods/ReactiveSwift/Sources/Scheduler.swift b/Example/Pods/ReactiveSwift/Sources/Scheduler.swift deleted file mode 100644 index 198fc48..0000000 --- a/Example/Pods/ReactiveSwift/Sources/Scheduler.swift +++ /dev/null @@ -1,551 +0,0 @@ -// -// Scheduler.swift -// ReactiveSwift -// -// Created by Justin Spahr-Summers on 2014-06-02. -// Copyright (c) 2014 GitHub. All rights reserved. -// - -import Dispatch -import Foundation - -#if os(Linux) - import let CDispatch.NSEC_PER_SEC -#endif - -/// Represents a serial queue of work items. -public protocol Scheduler { - /// Enqueues an action on the scheduler. - /// - /// When the work is executed depends on the scheduler in use. - /// - /// - parameters: - /// - action: The action to be scheduled. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - func schedule(_ action: @escaping () -> Void) -> Disposable? -} - -/// A particular kind of scheduler that supports enqueuing actions at future -/// dates. -public protocol DateScheduler: Scheduler { - /// The current date, as determined by this scheduler. - /// - /// This can be implemented to deterministically return a known date (e.g., - /// for testing purposes). - var currentDate: Date { get } - - /// Schedules an action for execution at or after the given date. - /// - /// - parameters: - /// - date: The start date. - /// - action: A closure of the action to be performed. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? - - /// Schedules a recurring action at the given interval, beginning at the - /// given date. - /// - /// - parameters: - /// - date: The start date. - /// - interval: A repetition interval. - /// - leeway: Some delta for repetition. - /// - action: A closure of the action to be performed. - /// - /// - note: If you plan to specify an `interval` value greater than 200,000 - /// seconds, use `schedule(after:interval:leeway:action)` instead - /// and specify your own `leeway` value to avoid potential overflow. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? -} - -/// A scheduler that performs all work synchronously. -public final class ImmediateScheduler: Scheduler { - public init() {} - - /// Immediately calls passed in `action`. - /// - /// - parameters: - /// - action: A closure of the action to be performed. - /// - /// - returns: `nil`. - @discardableResult - public func schedule(_ action: @escaping () -> Void) -> Disposable? { - action() - return nil - } -} - -/// A scheduler that performs all work on the main queue, as soon as possible. -/// -/// If the caller is already running on the main queue when an action is -/// scheduled, it may be run synchronously. However, ordering between actions -/// will always be preserved. -public final class UIScheduler: Scheduler { - private static let dispatchSpecificKey = DispatchSpecificKey() - private static let dispatchSpecificValue = UInt8.max - private static var __once: () = { - DispatchQueue.main.setSpecific(key: UIScheduler.dispatchSpecificKey, - value: dispatchSpecificValue) - }() - - #if os(Linux) - private var queueLength: Atomic = Atomic(0) - #else - // `inout` references do not guarantee atomicity. Use `UnsafeMutablePointer` - // instead. - // - // https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161205/004147.html - private let queueLength: UnsafeMutablePointer = { - let memory = UnsafeMutablePointer.allocate(capacity: 1) - memory.initialize(to: 0) - return memory - }() - - deinit { - queueLength.deinitialize() - queueLength.deallocate(capacity: 1) - } - #endif - - /// Initializes `UIScheduler` - public init() { - /// This call is to ensure the main queue has been setup appropriately - /// for `UIScheduler`. It is only called once during the application - /// lifetime, since Swift has a `dispatch_once` like mechanism to - /// lazily initialize global variables and static variables. - _ = UIScheduler.__once - } - - /// Queues an action to be performed on main queue. If the action is called - /// on the main thread and no work is queued, no scheduling takes place and - /// the action is called instantly. - /// - /// - parameters: - /// - action: A closure of the action to be performed on the main thread. - /// - /// - returns: `Disposable` that can be used to cancel the work before it - /// begins. - @discardableResult - public func schedule(_ action: @escaping () -> Void) -> Disposable? { - let disposable = SimpleDisposable() - let actionAndDecrement = { - if !disposable.isDisposed { - action() - } - - #if os(Linux) - self.queueLength.modify { $0 -= 1 } - #else - OSAtomicDecrement32(self.queueLength) - #endif - } - - #if os(Linux) - let queued = self.queueLength.modify { value -> Int32 in - value += 1 - return value - } - #else - let queued = OSAtomicIncrement32(queueLength) - #endif - - // If we're already running on the main queue, and there isn't work - // already enqueued, we can skip scheduling and just execute directly. - if queued == 1 && DispatchQueue.getSpecific(key: UIScheduler.dispatchSpecificKey) == UIScheduler.dispatchSpecificValue { - actionAndDecrement() - } else { - DispatchQueue.main.async(execute: actionAndDecrement) - } - - return disposable - } -} - -/// A scheduler backed by a serial GCD queue. -public final class QueueScheduler: DateScheduler { - /// A singleton `QueueScheduler` that always targets the main thread's GCD - /// queue. - /// - /// - note: Unlike `UIScheduler`, this scheduler supports scheduling for a - /// future date, and will always schedule asynchronously (even if - /// already running on the main thread). - public static let main = QueueScheduler(internalQueue: DispatchQueue.main) - - public var currentDate: Date { - return Date() - } - - public let queue: DispatchQueue - - internal init(internalQueue: DispatchQueue) { - queue = internalQueue - } - - /// Initializes a scheduler that will target the given queue with its - /// work. - /// - /// - note: Even if the queue is concurrent, all work items enqueued with - /// the `QueueScheduler` will be serial with respect to each other. - /// - /// - warning: Obsoleted in OS X 10.11 - @available(OSX, deprecated:10.10, obsoleted:10.11, message:"Use init(qos:name:targeting:) instead") - @available(iOS, deprecated:8.0, obsoleted:9.0, message:"Use init(qos:name:targeting:) instead.") - public convenience init(queue: DispatchQueue, name: String = "org.reactivecocoa.ReactiveSwift.QueueScheduler") { - self.init(internalQueue: DispatchQueue(label: name, target: queue)) - } - - /// Initializes a scheduler that creates a new serial queue with the - /// given quality of service class. - /// - /// - parameters: - /// - qos: Dispatch queue's QoS value. - /// - name: A name for the queue in the form of reverse domain. - /// - targeting: (Optional) The queue on which this scheduler's work is - /// targeted - @available(OSX 10.10, *) - public convenience init( - qos: DispatchQoS = .default, - name: String = "org.reactivecocoa.ReactiveSwift.QueueScheduler", - targeting targetQueue: DispatchQueue? = nil - ) { - self.init(internalQueue: DispatchQueue( - label: name, - qos: qos, - target: targetQueue - )) - } - - /// Schedules action for dispatch on internal queue - /// - /// - parameters: - /// - action: A closure of the action to be scheduled. - /// - /// - returns: `Disposable` that can be used to cancel the work before it - /// begins. - @discardableResult - public func schedule(_ action: @escaping () -> Void) -> Disposable? { - let d = SimpleDisposable() - - queue.async { - if !d.isDisposed { - action() - } - } - - return d - } - - private func wallTime(with date: Date) -> DispatchWallTime { - let (seconds, frac) = modf(date.timeIntervalSince1970) - - let nsec: Double = frac * Double(NSEC_PER_SEC) - let walltime = timespec(tv_sec: Int(seconds), tv_nsec: Int(nsec)) - - return DispatchWallTime(timespec: walltime) - } - - /// Schedules an action for execution at or after the given date. - /// - /// - parameters: - /// - date: The start date. - /// - action: A closure of the action to be performed. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? { - let d = SimpleDisposable() - - queue.asyncAfter(wallDeadline: wallTime(with: date)) { - if !d.isDisposed { - action() - } - } - - return d - } - - /// Schedules a recurring action at the given interval and beginning at the - /// given start date. A reasonable default timer interval leeway is - /// provided. - /// - /// - parameters: - /// - date: A date to schedule the first action for. - /// - interval: A repetition interval. - /// - action: Closure of the action to repeat. - /// - /// - note: If you plan to specify an `interval` value greater than 200,000 - /// seconds, use `schedule(after:interval:leeway:action)` instead - /// and specify your own `leeway` value to avoid potential overflow. - /// - /// - returns: Optional disposable that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after date: Date, interval: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { - // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of - // at least 10% of the timer interval. - return schedule(after: date, interval: interval, leeway: interval * 0.1, action: action) - } - - /// Schedules a recurring action at the given interval with provided leeway, - /// beginning at the given start time. - /// - /// - parameters: - /// - date: A date to schedule the first action for. - /// - interval: A repetition interval. - /// - leeway: Some delta for repetition interval. - /// - action: A closure of the action to repeat. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { - precondition(interval.timeInterval >= 0) - precondition(leeway.timeInterval >= 0) - - let timer = DispatchSource.makeTimerSource( - flags: DispatchSource.TimerFlags(rawValue: UInt(0)), - queue: queue - ) - timer.scheduleRepeating(wallDeadline: wallTime(with: date), - interval: interval, - leeway: leeway) - timer.setEventHandler(handler: action) - timer.resume() - - return ActionDisposable { - timer.cancel() - } - } -} - -/// A scheduler that implements virtualized time, for use in testing. -public final class TestScheduler: DateScheduler { - private final class ScheduledAction { - let date: Date - let action: () -> Void - - init(date: Date, action: @escaping () -> Void) { - self.date = date - self.action = action - } - - func less(_ rhs: ScheduledAction) -> Bool { - return date.compare(rhs.date) == .orderedAscending - } - } - - private let lock = NSRecursiveLock() - private var _currentDate: Date - - /// The virtual date that the scheduler is currently at. - public var currentDate: Date { - let d: Date - - lock.lock() - d = _currentDate - lock.unlock() - - return d - } - - private var scheduledActions: [ScheduledAction] = [] - - /// Initializes a TestScheduler with the given start date. - /// - /// - parameters: - /// - startDate: The start date of the scheduler. - public init(startDate: Date = Date(timeIntervalSinceReferenceDate: 0)) { - lock.name = "org.reactivecocoa.ReactiveSwift.TestScheduler" - _currentDate = startDate - } - - private func schedule(_ action: ScheduledAction) -> Disposable { - lock.lock() - scheduledActions.append(action) - scheduledActions.sort { $0.less($1) } - lock.unlock() - - return ActionDisposable { - self.lock.lock() - self.scheduledActions = self.scheduledActions.filter { $0 !== action } - self.lock.unlock() - } - } - - /// Enqueues an action on the scheduler. - /// - /// - note: The work is executed on `currentDate` as it is understood by the - /// scheduler. - /// - /// - parameters: - /// - action: An action that will be performed on scheduler's - /// `currentDate`. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(_ action: @escaping () -> Void) -> Disposable? { - return schedule(ScheduledAction(date: currentDate, action: action)) - } - - /// Schedules an action for execution after some delay. - /// - /// - parameters: - /// - delay: A delay for execution. - /// - action: A closure of the action to perform. - /// - /// - returns: Optional disposable that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after delay: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { - return schedule(after: currentDate.addingTimeInterval(delay), action: action) - } - - /// Schedules an action for execution at or after the given date. - /// - /// - parameters: - /// - date: A starting date. - /// - action: A closure of the action to perform. - /// - /// - returns: Optional disposable that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? { - return schedule(ScheduledAction(date: date, action: action)) - } - - /// Schedules a recurring action at the given interval, beginning at the - /// given start date. - /// - /// - parameters: - /// - date: A date to schedule the first action for. - /// - interval: A repetition interval. - /// - disposable: A disposable. - /// - action: A closure of the action to repeat. - /// - /// - note: If you plan to specify an `interval` value greater than 200,000 - /// seconds, use `schedule(after:interval:leeway:action)` instead - /// and specify your own `leeway` value to avoid potential overflow. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - private func schedule(after date: Date, interval: DispatchTimeInterval, disposable: SerialDisposable, action: @escaping () -> Void) { - precondition(interval.timeInterval >= 0) - - disposable.inner = schedule(after: date) { [unowned self] in - action() - self.schedule(after: date.addingTimeInterval(interval), interval: interval, disposable: disposable, action: action) - } - } - - /// Schedules a recurring action after given delay repeated at the given, - /// interval, beginning at the given interval counted from `currentDate`. - /// - /// - parameters: - /// - delay: A delay for action's dispatch. - /// - interval: A repetition interval. - /// - leeway: Some delta for repetition interval. - /// - action: A closure of the action to repeat. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - @discardableResult - public func schedule(after delay: DispatchTimeInterval, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .seconds(0), action: @escaping () -> Void) -> Disposable? { - return schedule(after: currentDate.addingTimeInterval(delay), interval: interval, leeway: leeway, action: action) - } - - /// Schedules a recurring action at the given interval with - /// provided leeway, beginning at the given start date. - /// - /// - parameters: - /// - date: A date to schedule the first action for. - /// - interval: A repetition interval. - /// - leeway: Some delta for repetition interval. - /// - action: A closure of the action to repeat. - /// - /// - returns: Optional `Disposable` that can be used to cancel the work - /// before it begins. - public func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .seconds(0), action: @escaping () -> Void) -> Disposable? { - let disposable = SerialDisposable() - schedule(after: date, interval: interval, disposable: disposable, action: action) - return disposable - } - - /// Advances the virtualized clock by an extremely tiny interval, dequeuing - /// and executing any actions along the way. - /// - /// This is intended to be used as a way to execute actions that have been - /// scheduled to run as soon as possible. - public func advance() { - advance(by: .nanoseconds(1)) - } - - /// Advances the virtualized clock by the given interval, dequeuing and - /// executing any actions along the way. - /// - /// - parameters: - /// - interval: Interval by which the current date will be advanced. - public func advance(by interval: DispatchTimeInterval) { - lock.lock() - advance(to: currentDate.addingTimeInterval(interval)) - lock.unlock() - } - - /// Advances the virtualized clock to the given future date, dequeuing and - /// executing any actions up until that point. - /// - /// - parameters: - /// - newDate: Future date to which the virtual clock will be advanced. - public func advance(to newDate: Date) { - lock.lock() - - assert(currentDate.compare(newDate) != .orderedDescending) - - while scheduledActions.count > 0 { - if newDate.compare(scheduledActions[0].date) == .orderedAscending { - break - } - - _currentDate = scheduledActions[0].date - - let scheduledAction = scheduledActions.remove(at: 0) - scheduledAction.action() - } - - _currentDate = newDate - - lock.unlock() - } - - /// Dequeues and executes all scheduled actions, leaving the scheduler's - /// date at `Date.distantFuture()`. - public func run() { - advance(to: Date.distantFuture) - } - - /// Rewinds the virtualized clock by the given interval. - /// This simulates that user changes device date. - /// - /// - parameters: - /// - interval: An interval by which the current date will be retreated. - public func rewind(by interval: DispatchTimeInterval) { - lock.lock() - - let newDate = currentDate.addingTimeInterval(-interval) - assert(currentDate.compare(newDate) != .orderedAscending) - _currentDate = newDate - - lock.unlock() - - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/Signal.swift b/Example/Pods/ReactiveSwift/Sources/Signal.swift deleted file mode 100644 index bb99337..0000000 --- a/Example/Pods/ReactiveSwift/Sources/Signal.swift +++ /dev/null @@ -1,2424 +0,0 @@ -import Foundation -import Result - -/// A push-driven stream that sends Events over time, parameterized by the type -/// of values being sent (`Value`) and the type of failure that can occur -/// (`Error`). If no failures should be possible, NoError can be specified for -/// `Error`. -/// -/// An observer of a Signal will see the exact same sequence of events as all -/// other observers. In other words, events will be sent to all observers at the -/// same time. -/// -/// Signals are generally used to represent event streams that are already “in -/// progress,” like notifications, user input, etc. To represent streams that -/// must first be _started_, see the SignalProducer type. -/// -/// A Signal is kept alive until either of the following happens: -/// 1. its input observer receives a terminating event; or -/// 2. it has no active observers, and is not being retained. -public final class Signal { - public typealias Observer = ReactiveSwift.Observer - - /// The disposable returned by the signal generator. It would be disposed of - /// when the signal terminates. - private var generatorDisposable: Disposable? - - /// The state of the signal. - /// - /// `state` synchronizes using Read-Copy-Update. Reads on the event delivery - /// routine are thus wait-free. But modifications, e.g. inserting observers, - /// still have to be serialized, and are required not to mutate in place. - /// - /// This suits `Signal` as reads to `status` happens on the critical path of - /// event delivery, while observers bag manipulation or termination generally - /// has a constant occurrence. - /// - /// As `SignalState` is a packed object reference (a tagged pointer) that is - /// naturally aligned, reads to are guaranteed to be atomic on all supported - /// hardware architectures of Swift (ARM and x86). - private var state: SignalState - - /// Used to ensure that state updates are serialized. - private let updateLock: NSLock - - /// Used to ensure that events are serialized during delivery to observers. - private let sendLock: NSLock - - /// Initialize a Signal that will immediately invoke the given generator, - /// then forward events sent to the given observer. - /// - /// - note: The disposable returned from the closure will be automatically - /// disposed if a terminating event is sent to the observer. The - /// Signal itself will remain alive until the observer is released. - /// - /// - parameters: - /// - generator: A closure that accepts an implicitly created observer - /// that will act as an event emitter for the signal. - public init(_ generator: (Observer) -> Disposable?) { - state = .alive(AliveState()) - updateLock = NSLock() - updateLock.name = "org.reactivecocoa.ReactiveSwift.Signal.updateLock" - sendLock = NSLock() - sendLock.name = "org.reactivecocoa.ReactiveSwift.Signal.sendLock" - - let observer = Observer { [weak self] event in - guard let signal = self else { - return - } - - // Thread Safety Notes on `Signal.state`. - // - // - Check if the signal is at a specific state. - // - // Read directly. - // - // - Deliver `value` events with the alive state. - // - // `sendLock` must be acquired. - // - // - Replace the alive state with another. - // (e.g. observers bag manipulation) - // - // `updateLock` must be acquired. - // - // - Transition from `alive` to `terminating` as a result of receiving - // a termination event. - // - // `updateLock` must be acquired, and should fail gracefully if the - // signal has terminated. - // - // - Check if the signal is terminating. If it is, invoke `tryTerminate` - // which transitions the state from `terminating` to `terminated`, and - // delivers the termination event. - // - // Both `sendLock` and `updateLock` must be acquired. The check can be - // relaxed, but the state must be checked again after the locks are - // acquired. Fail gracefully if the state has changed since the relaxed - // read, i.e. a concurrent sender has already handled the termination - // event. - // - // Exploiting the relaxation of reads, please note that false positives - // are intentionally allowed in the `terminating` checks below. As a - // result, normal event deliveries need not acquire `updateLock`. - // Nevertheless, this should not cause the termination event being - // sent multiple times, since `tryTerminate` would not respond to false - // positives. - - /// Try to terminate the signal. - /// - /// If the signal is alive or has terminated, it fails gracefully. In - /// other words, calling this method as a result of a false positive - /// `terminating` check is permitted. - /// - /// - note: The `updateLock` would be acquired. - /// - /// - returns: `true` if the attempt succeeds. `false` otherwise. - @inline(__always) - func tryTerminate() -> Bool { - // Acquire `updateLock`. If the termination has still not yet been - // handled, take it over and bump the status to `terminated`. - signal.updateLock.lock() - - if case let .terminating(state) = signal.state { - signal.state = .terminated - signal.updateLock.unlock() - - for observer in state.observers { - observer.action(state.event) - } - - return true - } - - signal.updateLock.unlock() - return false - } - - if event.isTerminating { - // Recursive events are disallowed for `value` events, but are permitted - // for termination events. Specifically: - // - // - `interrupted` - // It can inadvertently be sent by downstream consumers as part of the - // `SignalProducer` mechanics. - // - // - `completed` - // If a downstream consumer weakly references an object, invocation of - // such consumer may cause a race condition with its weak retain against - // the last strong release of the object. If the `Lifetime` of the - // object is being referenced by an upstream `take(during:)`, a - // signal recursion might occur. - // - // So we would treat termination events specially. If it happens to - // occur while the `sendLock` is acquired, the observer call-out and - // the disposal would be delegated to the current sender, or - // occasionally one of the senders waiting on `sendLock`. - signal.updateLock.lock() - - if case let .alive(state) = signal.state { - let newSnapshot = TerminatingState(observers: state.observers, - event: event) - signal.state = .terminating(newSnapshot) - signal.updateLock.unlock() - - if signal.sendLock.try() { - // Check whether the terminating state has been handled by a - // concurrent sender. If not, handle it. - let shouldDispose = tryTerminate() - signal.sendLock.unlock() - - if shouldDispose { - signal.swapDisposable()?.dispose() - } - } - } else { - signal.updateLock.unlock() - } - } else { - var shouldDispose = false - - // The `terminating` status check is performed twice for two different - // purposes: - // - // 1. Within the main protected section - // It guarantees that a recursive termination event sent by a - // downstream consumer, is immediately processed and need not compete - // with concurrent pending senders (if any). - // - // Termination events sent concurrently may also be caught here, but - // not necessarily all of them due to data races. - // - // 2. After the main protected section - // It ensures the termination event sent concurrently that are not - // caught by (1) due to data races would still be processed. - // - // The related PR on the race conditions: - // https://github.com/ReactiveCocoa/ReactiveSwift/pull/112 - - signal.sendLock.lock() - // Start of the main protected section. - - if case let .alive(state) = signal.state { - for observer in state.observers { - observer.action(event) - } - - // Check if the status has been bumped to `terminating` due to a - // concurrent or a recursive termination event. - if case .terminating = signal.state { - shouldDispose = tryTerminate() - } - } - - // End of the main protected section. - signal.sendLock.unlock() - - // Check if the status has been bumped to `terminating` due to a - // concurrent termination event that has not been caught in the main - // protected section. - if !shouldDispose, case .terminating = signal.state { - signal.sendLock.lock() - shouldDispose = tryTerminate() - signal.sendLock.unlock() - } - - if shouldDispose { - // Dispose only after notifying observers, so disposal - // logic is consistently the last thing to run. - signal.swapDisposable()?.dispose() - } - } - } - - generatorDisposable = generator(observer) - } - - /// Swap the generator disposable with `nil`. - /// - /// - returns: - /// The generator disposable, or `nil` if it has been disposed of. - private func swapDisposable() -> Disposable? { - if let d = generatorDisposable { - generatorDisposable = nil - return d - } - return nil - } - - deinit { - // A signal can deinitialize only when it is not retained and has no - // active observers. So `state` need not be swapped. - swapDisposable()?.dispose() - } - - /// A Signal that never sends any events to its observers. - public static var never: Signal { - return self.init { _ in nil } - } - - /// A Signal that completes immediately without emitting any value. - public static var empty: Signal { - return self.init { observer in - observer.sendCompleted() - return nil - } - } - - /// Create a `Signal` that will be controlled by sending events to an - /// input observer. - /// - /// - note: The `Signal` will remain alive until a terminating event is sent - /// to the input observer, or until it has no observers and there - /// are no strong references to it. - /// - /// - parameters: - /// - disposable: An optional disposable to associate with the signal, and - /// to be disposed of when the signal terminates. - /// - /// - returns: A tuple of `output: Signal`, the output end of the pipe, - /// and `input: Observer`, the input end of the pipe. - public static func pipe(disposable: Disposable? = nil) -> (output: Signal, input: Observer) { - var observer: Observer! - let signal = self.init { innerObserver in - observer = innerObserver - return disposable - } - - return (signal, observer) - } - - /// Observe the Signal by sending any future events to the given observer. - /// - /// - note: If the Signal has already terminated, the observer will - /// immediately receive an `interrupted` event. - /// - /// - parameters: - /// - observer: An observer to forward the events to. - /// - /// - returns: A `Disposable` which can be used to disconnect the observer, - /// or `nil` if the signal has already terminated. - @discardableResult - public func observe(_ observer: Observer) -> Disposable? { - var token: RemovalToken? - updateLock.lock() - if case let .alive(snapshot) = state { - var observers = snapshot.observers - token = observers.insert(observer) - state = .alive(AliveState(observers: observers, retaining: self)) - } - updateLock.unlock() - - if let token = token { - return ActionDisposable { [weak self] in - if let s = self { - s.updateLock.lock() - - if case let .alive(snapshot) = s.state { - var observers = snapshot.observers - observers.remove(using: token) - - // Ensure the old signal state snapshot does not deinitialize before - // `updateLock` is released. Otherwise, it might result in a - // deadlock in cases where a `Signal` legitimately receives terminal - // events recursively as a result of the deinitialization of the - // snapshot. - withExtendedLifetime(snapshot) { - s.state = .alive(AliveState(observers: observers, - retaining: observers.isEmpty ? nil : self)) - s.updateLock.unlock() - } - } else { - s.updateLock.unlock() - } - } - } - } else { - observer.sendInterrupted() - return nil - } - } -} - -/// The state of a `Signal`. -/// -/// `SignalState` is guaranteed to be laid out as a tagged pointer by the Swift -/// compiler in the support targets of the Swift 3.0.1 ABI. -/// -/// The Swift compiler has also an optimization for enums with payloads that are -/// all reference counted, and at most one no-payload case. -private enum SignalState { - /// The `Signal` is alive. - case alive(AliveState) - - /// The `Signal` has received a termination event, and is about to be - /// terminated. - case terminating(TerminatingState) - - /// The `Signal` has terminated. - case terminated -} - -// As the amount of state would definitely span over a cache line, -// `AliveState` and `TerminatingState` is set to be a reference type so -// that we can atomically update the reference instead. -// -// Note that in-place mutation should not be introduced to `AliveState` and -// `TerminatingState`. Copy the states and create a new instance. - -/// The state of a `Signal` that is alive. It contains a bag of observers and -/// an optional self-retaining reference. -private final class AliveState { - /// The observers of the `Signal`. - fileprivate let observers: Bag.Observer> - - /// A self-retaining reference. It is set when there are one or more active - /// observers. - fileprivate let retaining: Signal? - - /// Create an alive state. - /// - /// - parameters: - /// - observers: The latest bag of observers. - /// - retaining: The self-retaining reference of the `Signal`, if necessary. - init(observers: Bag.Observer> = Bag(), retaining: Signal? = nil) { - self.observers = observers - self.retaining = retaining - } -} - -/// The state of a terminating `Signal`. It contains a bag of observers and the -/// termination event. -private final class TerminatingState { - /// The observers of the `Signal`. - fileprivate let observers: Bag.Observer> - - /// The termination event. - fileprivate let event: Event - - /// Create a terminating state. - /// - /// - parameters: - /// - observers: The latest bag of observers. - /// - event: The termination event. - init(observers: Bag.Observer>, event: Event) { - self.observers = observers - self.event = event - } -} - -/// A protocol used to constraint `Signal` operators. -public protocol SignalProtocol { - /// The type of values being sent on the signal. - associatedtype Value - - /// The type of error that can occur on the signal. If errors aren't - /// possible then `NoError` can be used. - associatedtype Error: Swift.Error - - /// Extracts a signal from the receiver. - var signal: Signal { get } - - /// Observes the Signal by sending any future events to the given observer. - @discardableResult - func observe(_ observer: Signal.Observer) -> Disposable? -} - -extension Signal: SignalProtocol { - public var signal: Signal { - return self - } -} - -extension SignalProtocol { - /// Convenience override for observe(_:) to allow trailing-closure style - /// invocations. - /// - /// - parameters: - /// - action: A closure that will accept an event of the signal - /// - /// - returns: An optional `Disposable` which can be used to stop the - /// invocation of the callback. Disposing of the Disposable will - /// have no effect on the Signal itself. - @discardableResult - public func observe(_ action: @escaping Signal.Observer.Action) -> Disposable? { - return observe(Observer(action)) - } - - /// Observe the `Signal` by invoking the given callback when `value` or - /// `failed` event are received. - /// - /// - parameters: - /// - result: A closure that accepts instance of `Result` - /// enum that contains either a `.success(Value)` or - /// `.failure` case. - /// - /// - returns: An optional `Disposable` which can be used to stop the - /// invocation of the callback. Disposing of the Disposable will - /// have no effect on the Signal itself. - @discardableResult - public func observeResult(_ result: @escaping (Result) -> Void) -> Disposable? { - return observe( - Observer( - value: { result(.success($0)) }, - failed: { result(.failure($0)) } - ) - ) - } - - /// Observe the `Signal` by invoking the given callback when a `completed` - /// event is received. - /// - /// - parameters: - /// - completed: A closure that is called when `completed` event is - /// received. - /// - /// - returns: An optional `Disposable` which can be used to stop the - /// invocation of the callback. Disposing of the Disposable will - /// have no effect on the Signal itself. - @discardableResult - public func observeCompleted(_ completed: @escaping () -> Void) -> Disposable? { - return observe(Observer(completed: completed)) - } - - /// Observe the `Signal` by invoking the given callback when a `failed` - /// event is received. - /// - /// - parameters: - /// - error: A closure that is called when failed event is received. It - /// accepts an error parameter. - /// - /// Returns a Disposable which can be used to stop the invocation of the - /// callback. Disposing of the Disposable will have no effect on the Signal - /// itself. - @discardableResult - public func observeFailed(_ error: @escaping (Error) -> Void) -> Disposable? { - return observe(Observer(failed: error)) - } - - /// Observe the `Signal` by invoking the given callback when an - /// `interrupted` event is received. If the Signal has already terminated, - /// the callback will be invoked immediately. - /// - /// - parameters: - /// - interrupted: A closure that is invoked when `interrupted` event is - /// received - /// - /// - returns: An optional `Disposable` which can be used to stop the - /// invocation of the callback. Disposing of the Disposable will - /// have no effect on the Signal itself. - @discardableResult - public func observeInterrupted(_ interrupted: @escaping () -> Void) -> Disposable? { - return observe(Observer(interrupted: interrupted)) - } -} - -extension SignalProtocol where Error == NoError { - /// Observe the Signal by invoking the given callback when `value` events are - /// received. - /// - /// - parameters: - /// - value: A closure that accepts a value when `value` event is received. - /// - /// - returns: An optional `Disposable` which can be used to stop the - /// invocation of the callback. Disposing of the Disposable will - /// have no effect on the Signal itself. - @discardableResult - public func observeValues(_ value: @escaping (Value) -> Void) -> Disposable? { - return observe(Observer(value: value)) - } -} - -extension SignalProtocol { - /// Map each value in the signal to a new value. - /// - /// - parameters: - /// - transform: A closure that accepts a value from the `value` event and - /// returns a new value. - /// - /// - returns: A signal that will send new values. - public func map(_ transform: @escaping (Value) -> U) -> Signal { - return Signal { observer in - return self.observe { event in - observer.action(event.map(transform)) - } - } - } - - /// Map errors in the signal to a new error. - /// - /// - parameters: - /// - transform: A closure that accepts current error object and returns - /// a new type of error object. - /// - /// - returns: A signal that will send new type of errors. - public func mapError(_ transform: @escaping (Error) -> F) -> Signal { - return Signal { observer in - return self.observe { event in - observer.action(event.mapError(transform)) - } - } - } - - /// Maps each value in the signal to a new value, lazily evaluating the - /// supplied transformation on the specified scheduler. - /// - /// - important: Unlike `map`, there is not a 1-1 mapping between incoming - /// values, and values sent on the returned signal. If - /// `scheduler` has not yet scheduled `transform` for - /// execution, then each new value will replace the last one as - /// the parameter to `transform` once it is finally executed. - /// - /// - parameters: - /// - transform: The closure used to obtain the returned value from this - /// signal's underlying value. - /// - /// - returns: A signal that sends values obtained using `transform` as this - /// signal sends values. - public func lazyMap(on scheduler: Scheduler, transform: @escaping (Value) -> U) -> Signal { - return flatMap(.latest) { value in - return SignalProducer({ transform(value) }) - .start(on: scheduler) - } - } - - /// Preserve only the values of the signal that pass the given predicate. - /// - /// - parameters: - /// - predicate: A closure that accepts value and returns `Bool` denoting - /// whether value has passed the test. - /// - /// - returns: A signal that will send only the values passing the given - /// predicate. - public func filter(_ predicate: @escaping (Value) -> Bool) -> Signal { - return Signal { observer in - return self.observe { (event: Event) -> Void in - guard let value = event.value else { - observer.action(event) - return - } - - if predicate(value) { - observer.send(value: value) - } - } - } - } - - /// Applies `transform` to values from `signal` and forwards values with non `nil` results unwrapped. - /// - parameters: - /// - transform: A closure that accepts a value from the `value` event and - /// returns a new optional value. - /// - /// - returns: A signal that will send new values, that are non `nil` after the transformation. - public func filterMap(_ transform: @escaping (Value) -> U?) -> Signal { - return Signal { observer in - return self.observe { (event: Event) -> Void in - switch event { - case let .value(value): - if let mapped = transform(value) { - observer.send(value: mapped) - } - case let .failed(error): - observer.send(error: error) - case .completed: - observer.sendCompleted() - case .interrupted: - observer.sendInterrupted() - } - } - } - } -} - -extension SignalProtocol where Value: OptionalProtocol { - /// Unwrap non-`nil` values and forward them on the returned signal, `nil` - /// values are dropped. - /// - /// - returns: A signal that sends only non-nil values. - public func skipNil() -> Signal { - return filter { $0.optional != nil }.map { $0.optional! } - } -} - -extension SignalProtocol { - /// Take up to `n` values from the signal and then complete. - /// - /// - precondition: `count` must be non-negative number. - /// - /// - parameters: - /// - count: A number of values to take from the signal. - /// - /// - returns: A signal that will yield the first `count` values from `self` - public func take(first count: Int) -> Signal { - precondition(count >= 0) - - return Signal { observer in - if count == 0 { - observer.sendCompleted() - return nil - } - - var taken = 0 - - return self.observe { event in - guard let value = event.value else { - observer.action(event) - return - } - - if taken < count { - taken += 1 - observer.send(value: value) - } - - if taken == count { - observer.sendCompleted() - } - } - } - } -} - -/// A reference type which wraps an array to auxiliate the collection of values -/// for `collect` operator. -private final class CollectState { - var values: [Value] = [] - - /// Collects a new value. - func append(_ value: Value) { - values.append(value) - } - - /// Check if there are any items remaining. - /// - /// - note: This method also checks if there weren't collected any values - /// and, in that case, it means an empty array should be sent as the - /// result of collect. - var isEmpty: Bool { - /// We use capacity being zero to determine if we haven't collected any - /// value since we're keeping the capacity of the array to avoid - /// unnecessary and expensive allocations). This also guarantees - /// retro-compatibility around the original `collect()` operator. - return values.isEmpty && values.capacity > 0 - } - - /// Removes all values previously collected if any. - func flush() { - // Minor optimization to avoid consecutive allocations. Can - // be useful for sequences of regular or similar size and to - // track if any value was ever collected. - values.removeAll(keepingCapacity: true) - } -} - -extension SignalProtocol { - /// Collect all values sent by the signal then forward them as a single - /// array and complete. - /// - /// - note: When `self` completes without collecting any value, it will send - /// an empty array of values. - /// - /// - returns: A signal that will yield an array of values when `self` - /// completes. - public func collect() -> Signal<[Value], Error> { - return collect { _,_ in false } - } - - /// Collect at most `count` values from `self`, forward them as a single - /// array and complete. - /// - /// - note: When the count is reached the array is sent and the signal - /// starts over yielding a new array of values. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not have `count` values. Alternatively, if were - /// not collected any values will sent an empty array of values. - /// - /// - precondition: `count` should be greater than zero. - /// - public func collect(count: Int) -> Signal<[Value], Error> { - precondition(count > 0) - return collect { values in values.count == count } - } - - /// Collect values that pass the given predicate then forward them as a - /// single array and complete. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not match `predicate`. Alternatively, if were not - /// collected any values will sent an empty array of values. - /// - /// ```` - /// let (signal, observer) = Signal.pipe() - /// - /// signal - /// .collect { values in values.reduce(0, combine: +) == 8 } - /// .observeValues { print($0) } - /// - /// observer.send(value: 1) - /// observer.send(value: 3) - /// observer.send(value: 4) - /// observer.send(value: 7) - /// observer.send(value: 1) - /// observer.send(value: 5) - /// observer.send(value: 6) - /// observer.sendCompleted() - /// - /// // Output: - /// // [1, 3, 4] - /// // [7, 1] - /// // [5, 6] - /// ```` - /// - /// - parameters: - /// - predicate: Predicate to match when values should be sent (returning - /// `true`) or alternatively when they should be collected - /// (where it should return `false`). The most recent value - /// (`value`) is included in `values` and will be the end of - /// the current array of values if the predicate returns - /// `true`. - /// - /// - returns: A signal that collects values passing the predicate and, when - /// `self` completes, forwards them as a single array and - /// complets. - public func collect(_ predicate: @escaping (_ values: [Value]) -> Bool) -> Signal<[Value], Error> { - return Signal { observer in - let state = CollectState() - - return self.observe { event in - switch event { - case let .value(value): - state.append(value) - if predicate(state.values) { - observer.send(value: state.values) - state.flush() - } - case .completed: - if !state.isEmpty { - observer.send(value: state.values) - } - observer.sendCompleted() - case let .failed(error): - observer.send(error: error) - case .interrupted: - observer.sendInterrupted() - } - } - } - } - - /// Repeatedly collect an array of values up to a matching `value` value. - /// Then forward them as single array and wait for value events. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not match `predicate`. Alternatively, if no - /// values were collected an empty array will be sent. - /// - /// ```` - /// let (signal, observer) = Signal.pipe() - /// - /// signal - /// .collect { values, value in value == 7 } - /// .observeValues { print($0) } - /// - /// observer.send(value: 1) - /// observer.send(value: 1) - /// observer.send(value: 7) - /// observer.send(value: 7) - /// observer.send(value: 5) - /// observer.send(value: 6) - /// observer.sendCompleted() - /// - /// // Output: - /// // [1, 1] - /// // [7] - /// // [7, 5, 6] - /// ```` - /// - /// - parameters: - /// - predicate: Predicate to match when values should be sent (returning - /// `true`) or alternatively when they should be collected - /// (where it should return `false`). The most recent value - /// (`value`) is not included in `values` and will be the - /// start of the next array of values if the predicate - /// returns `true`. - /// - /// - returns: A signal that will yield an array of values based on a - /// predicate which matches the values collected and the next - /// value. - public func collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool) -> Signal<[Value], Error> { - return Signal { observer in - let state = CollectState() - - return self.observe { event in - switch event { - case let .value(value): - if predicate(state.values, value) { - observer.send(value: state.values) - state.flush() - } - state.append(value) - case .completed: - if !state.isEmpty { - observer.send(value: state.values) - } - observer.sendCompleted() - case let .failed(error): - observer.send(error: error) - case .interrupted: - observer.sendInterrupted() - } - } - } - } - - /// Forward all events onto the given scheduler, instead of whichever - /// scheduler they originally arrived upon. - /// - /// - parameters: - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A signal that will yield `self` values on provided scheduler. - public func observe(on scheduler: Scheduler) -> Signal { - return Signal { observer in - return self.observe { event in - scheduler.schedule { - observer.action(event) - } - } - } - } -} - -private final class CombineLatestState { - var latestValue: Value? - var isCompleted = false -} - -extension SignalProtocol { - private func observeWithStates(_ signalState: CombineLatestState, _ otherState: CombineLatestState, _ lock: NSLock, _ observer: Signal<(), Error>.Observer) -> Disposable? { - return self.observe { event in - switch event { - case let .value(value): - lock.lock() - - signalState.latestValue = value - if otherState.latestValue != nil { - observer.send(value: ()) - } - - lock.unlock() - - case let .failed(error): - observer.send(error: error) - - case .completed: - lock.lock() - - signalState.isCompleted = true - if otherState.isCompleted { - observer.sendCompleted() - } - - lock.unlock() - - case .interrupted: - observer.sendInterrupted() - } - } - } - - /// Combine the latest value of the receiver with the latest value from the - /// given signal. - /// - /// - note: The returned signal will not send a value until both inputs have - /// sent at least one value each. - /// - /// - note: If either signal is interrupted, the returned signal will also - /// be interrupted. - /// - /// - note: The returned signal will not complete until both inputs - /// complete. - /// - /// - parameters: - /// - otherSignal: A signal to combine `self`'s value with. - /// - /// - returns: A signal that will yield a tuple containing values of `self` - /// and given signal. - public func combineLatest(with other: Signal) -> Signal<(Value, U), Error> { - return Signal { observer in - let lock = NSLock() - lock.name = "org.reactivecocoa.ReactiveSwift.combineLatestWith" - - let signalState = CombineLatestState() - let otherState = CombineLatestState() - - let onBothValue = { - observer.send(value: (signalState.latestValue!, otherState.latestValue!)) - } - - let observer = Signal<(), Error>.Observer(value: onBothValue, failed: observer.send(error:), completed: observer.sendCompleted, interrupted: observer.sendInterrupted) - - let disposable = CompositeDisposable() - disposable += self.observeWithStates(signalState, otherState, lock, observer) - disposable += other.observeWithStates(otherState, signalState, lock, observer) - - return disposable - } - } - - /// Delay `value` and `completed` events by the given interval, forwarding - /// them on the given scheduler. - /// - /// - note: failed and `interrupted` events are always scheduled - /// immediately. - /// - /// - parameters: - /// - interval: Interval to delay `value` and `completed` events by. - /// - scheduler: A scheduler to deliver delayed events on. - /// - /// - returns: A signal that will delay `value` and `completed` events and - /// will yield them on given scheduler. - public func delay(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { - precondition(interval >= 0) - - return Signal { observer in - return self.observe { event in - switch event { - case .failed, .interrupted: - scheduler.schedule { - observer.action(event) - } - - case .value, .completed: - let date = scheduler.currentDate.addingTimeInterval(interval) - scheduler.schedule(after: date) { - observer.action(event) - } - } - } - } - } - - /// Skip first `count` number of values then act as usual. - /// - /// - parameters: - /// - count: A number of values to skip. - /// - /// - returns: A signal that will skip the first `count` values, then - /// forward everything afterward. - public func skip(first count: Int) -> Signal { - precondition(count >= 0) - - if count == 0 { - return signal - } - - return Signal { observer in - var skipped = 0 - - return self.observe { event in - if case .value = event, skipped < count { - skipped += 1 - } else { - observer.action(event) - } - } - } - } - - /// Treat all Events from `self` as plain values, allowing them to be - /// manipulated just like any other value. - /// - /// In other words, this brings Events “into the monad”. - /// - /// - note: When a Completed or Failed event is received, the resulting - /// signal will send the Event itself and then complete. When an - /// Interrupted event is received, the resulting signal will send - /// the Event itself and then interrupt. - /// - /// - returns: A signal that sends events as its values. - public func materialize() -> Signal, NoError> { - return Signal { observer in - return self.observe { event in - observer.send(value: event) - - switch event { - case .interrupted: - observer.sendInterrupted() - - case .completed, .failed: - observer.sendCompleted() - - case .value: - break - } - } - } - } -} - -extension SignalProtocol where Value: EventProtocol, Error == NoError { - /// Translate a signal of `Event` _values_ into a signal of those events - /// themselves. - /// - /// - returns: A signal that sends values carried by `self` events. - public func dematerialize() -> Signal { - return Signal { observer in - return self.observe { event in - switch event { - case let .value(innerEvent): - observer.action(innerEvent.event) - - case .failed: - fatalError("NoError is impossible to construct") - - case .completed: - observer.sendCompleted() - - case .interrupted: - observer.sendInterrupted() - } - } - } - } -} - -extension SignalProtocol { - /// Inject side effects to be performed upon the specified signal events. - /// - /// - parameters: - /// - event: A closure that accepts an event and is invoked on every - /// received event. - /// - failed: A closure that accepts error object and is invoked for - /// failed event. - /// - completed: A closure that is invoked for `completed` event. - /// - interrupted: A closure that is invoked for `interrupted` event. - /// - terminated: A closure that is invoked for any terminating event. - /// - disposed: A closure added as disposable when signal completes. - /// - value: A closure that accepts a value from `value` event. - /// - /// - returns: A signal with attached side-effects for given event cases. - public func on( - event: ((Event) -> Void)? = nil, - failed: ((Error) -> Void)? = nil, - completed: (() -> Void)? = nil, - interrupted: (() -> Void)? = nil, - terminated: (() -> Void)? = nil, - disposed: (() -> Void)? = nil, - value: ((Value) -> Void)? = nil - ) -> Signal { - return Signal { observer in - let disposable = CompositeDisposable() - - _ = disposed.map(disposable.add) - - disposable += signal.observe { receivedEvent in - event?(receivedEvent) - - switch receivedEvent { - case let .value(v): - value?(v) - - case let .failed(error): - failed?(error) - - case .completed: - completed?() - - case .interrupted: - interrupted?() - } - - if receivedEvent.isTerminating { - terminated?() - } - - observer.action(receivedEvent) - } - - return disposable - } - } -} - -private struct SampleState { - var latestValue: Value? = nil - var isSignalCompleted: Bool = false - var isSamplerCompleted: Bool = false -} - -extension SignalProtocol { - /// Forward the latest value from `self` with the value from `sampler` as a - /// tuple, only when`sampler` sends a `value` event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - sampler: A signal that will trigger the delivery of `value` event - /// from `self`. - /// - /// - returns: A signal that will send values from `self` and `sampler`, - /// sampled (possibly multiple times) by `sampler`, then complete - /// once both input signals have completed, or interrupt if - /// either input signal is interrupted. - public func sample(with sampler: Signal) -> Signal<(Value, T), Error> { - return Signal { observer in - let state = Atomic(SampleState()) - let disposable = CompositeDisposable() - - disposable += self.observe { event in - switch event { - case let .value(value): - state.modify { - $0.latestValue = value - } - - case let .failed(error): - observer.send(error: error) - - case .completed: - let shouldComplete: Bool = state.modify { - $0.isSignalCompleted = true - return $0.isSamplerCompleted - } - - if shouldComplete { - observer.sendCompleted() - } - - case .interrupted: - observer.sendInterrupted() - } - } - - disposable += sampler.observe { event in - switch event { - case .value(let samplerValue): - if let value = state.value.latestValue { - observer.send(value: (value, samplerValue)) - } - - case .completed: - let shouldComplete: Bool = state.modify { - $0.isSamplerCompleted = true - return $0.isSignalCompleted - } - - if shouldComplete { - observer.sendCompleted() - } - - case .interrupted: - observer.sendInterrupted() - - case .failed: - break - } - } - - return disposable - } - } - - /// Forward the latest value from `self` whenever `sampler` sends a `value` - /// event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - sampler: A signal that will trigger the delivery of `value` event - /// from `self`. - /// - /// - returns: A signal that will send values from `self`, sampled (possibly - /// multiple times) by `sampler`, then complete once both input - /// signals have completed, or interrupt if either input signal - /// is interrupted. - public func sample(on sampler: Signal<(), NoError>) -> Signal { - return sample(with: sampler) - .map { $0.0 } - } - - /// Forward the latest value from `samplee` with the value from `self` as a - /// tuple, only when `self` sends a `value` event. - /// This is like a flipped version of `sample(with:)`, but `samplee`'s - /// terminal events are completely ignored. - /// - /// - note: If `self` fires before a value has been observed on `samplee`, - /// nothing happens. - /// - /// - parameters: - /// - samplee: A signal whose latest value is sampled by `self`. - /// - /// - returns: A signal that will send values from `self` and `samplee`, - /// sampled (possibly multiple times) by `self`, then terminate - /// once `self` has terminated. **`samplee`'s terminated events - /// are ignored**. - public func withLatest(from samplee: Signal) -> Signal<(Value, U), Error> { - return Signal { observer in - let state = Atomic(nil) - let disposable = CompositeDisposable() - - disposable += samplee.observeValues { value in - state.value = value - } - - disposable += self.observe { event in - switch event { - case let .value(value): - if let value2 = state.value { - observer.send(value: (value, value2)) - } - case .completed: - observer.sendCompleted() - case let .failed(error): - observer.send(error: error) - case .interrupted: - observer.sendInterrupted() - } - } - - return disposable - } - } - - /// Forward the latest value from `samplee` with the value from `self` as a - /// tuple, only when `self` sends a `value` event. - /// This is like a flipped version of `sample(with:)`, but `samplee`'s - /// terminal events are completely ignored. - /// - /// - note: If `self` fires before a value has been observed on `samplee`, - /// nothing happens. - /// - /// - parameters: - /// - samplee: A producer whose latest value is sampled by `self`. - /// - /// - returns: A signal that will send values from `self` and `samplee`, - /// sampled (possibly multiple times) by `self`, then terminate - /// once `self` has terminated. **`samplee`'s terminated events - /// are ignored**. - public func withLatest(from samplee: SignalProducer) -> Signal<(Value, U), Error> { - return Signal { observer in - let d = CompositeDisposable() - samplee.startWithSignal { signal, disposable in - d += disposable - d += self.withLatest(from: signal).observe(observer) - } - return d - } - } -} - -extension SignalProtocol { - /// Forwards events from `self` until `lifetime` ends, at which point the - /// returned signal will complete. - /// - /// - parameters: - /// - lifetime: A lifetime whose `ended` signal will cause the returned - /// signal to complete. - /// - /// - returns: A signal that will deliver events until `lifetime` ends. - public func take(during lifetime: Lifetime) -> Signal { - return Signal { observer in - let disposable = CompositeDisposable() - disposable += self.observe(observer) - disposable += lifetime.observeEnded(observer.sendCompleted) - return disposable - } - } - - /// Forward events from `self` until `trigger` sends a `value` or - /// `completed` event, at which point the returned signal will complete. - /// - /// - parameters: - /// - trigger: A signal whose `value` or `completed` events will stop the - /// delivery of `value` events from `self`. - /// - /// - returns: A signal that will deliver events until `trigger` sends - /// `value` or `completed` events. - public func take(until trigger: Signal<(), NoError>) -> Signal { - return Signal { observer in - let disposable = CompositeDisposable() - disposable += self.observe(observer) - - disposable += trigger.observe { event in - switch event { - case .value, .completed: - observer.sendCompleted() - - case .failed, .interrupted: - break - } - } - - return disposable - } - } - - /// Do not forward any values from `self` until `trigger` sends a `value` or - /// `completed` event, at which point the returned signal behaves exactly - /// like `signal`. - /// - /// - parameters: - /// - trigger: A signal whose `value` or `completed` events will start the - /// deliver of events on `self`. - /// - /// - returns: A signal that will deliver events once the `trigger` sends - /// `value` or `completed` events. - public func skip(until trigger: Signal<(), NoError>) -> Signal { - return Signal { observer in - let disposable = SerialDisposable() - - disposable.inner = trigger.observe { event in - switch event { - case .value, .completed: - disposable.inner = self.observe(observer) - - case .failed, .interrupted: - break - } - } - - return disposable - } - } - - /// Forward events from `self` with history: values of the returned signal - /// are a tuples whose first member is the previous value and whose second member - /// is the current value. `initial` is supplied as the first member when `self` - /// sends its first value. - /// - /// - parameters: - /// - initial: A value that will be combined with the first value sent by - /// `self`. - /// - /// - returns: A signal that sends tuples that contain previous and current - /// sent values of `self`. - public func combinePrevious(_ initial: Value) -> Signal<(Value, Value), Error> { - return scan((initial, initial)) { previousCombinedValues, newValue in - return (previousCombinedValues.1, newValue) - } - } - - - /// Send only the final value and then immediately completes. - /// - /// - parameters: - /// - initial: Initial value for the accumulator. - /// - combine: A closure that accepts accumulator and sent value of - /// `self`. - /// - /// - returns: A signal that sends accumulated value after `self` completes. - public func reduce(_ initial: U, _ combine: @escaping (U, Value) -> U) -> Signal { - // We need to handle the special case in which `signal` sends no values. - // We'll do that by sending `initial` on the output signal (before - // taking the last value). - let (scannedSignalWithInitialValue, outputSignalObserver) = Signal.pipe() - let outputSignal = scannedSignalWithInitialValue.take(last: 1) - - // Now that we've got takeLast() listening to the piped signal, send - // that initial value. - outputSignalObserver.send(value: initial) - - // Pipe the scanned input signal into the output signal. - self.scan(initial, combine) - .observe(outputSignalObserver) - - return outputSignal - } - - /// Aggregate values into a single combined value. When `self` emits its - /// first value, `combine` is invoked with `initial` as the first argument - /// and that emitted value as the second argument. The result is emitted - /// from the signal returned from `scan`. That result is then passed to - /// `combine` as the first argument when the next value is emitted, and so - /// on. - /// - /// - parameters: - /// - initial: Initial value for the accumulator. - /// - combine: A closure that accepts accumulator and sent value of - /// `self`. - /// - /// - returns: A signal that sends accumulated value each time `self` emits - /// own value. - public func scan(_ initial: U, _ combine: @escaping (U, Value) -> U) -> Signal { - return Signal { observer in - var accumulator = initial - - return self.observe { event in - observer.action(event.map { value in - accumulator = combine(accumulator, value) - return accumulator - }) - } - } - } -} - -extension SignalProtocol where Value: Equatable { - /// Forward only those values from `self` which are not duplicates of the - /// immedately preceding value. - /// - /// - note: The first value is always forwarded. - /// - /// - returns: A signal that does not send two equal values sequentially. - public func skipRepeats() -> Signal { - return skipRepeats(==) - } -} - -extension SignalProtocol { - /// Forward only those values from `self` which do not pass `isRepeat` with - /// respect to the previous value. - /// - /// - note: The first value is always forwarded. - /// - /// - parameters: - /// - isRepeate: A closure that accepts previous and current values of - /// `self` and returns `Bool` whether these values are - /// repeating. - /// - /// - returns: A signal that forwards only those values that fail given - /// `isRepeat` predicate. - public func skipRepeats(_ isRepeat: @escaping (Value, Value) -> Bool) -> Signal { - return self - .scan((nil, false)) { (accumulated: (Value?, Bool), next: Value) -> (value: Value?, repeated: Bool) in - switch accumulated.0 { - case nil: - return (next, false) - case let prev? where isRepeat(prev, next): - return (prev, true) - case _?: - return (Optional(next), false) - } - } - .filter { !$0.repeated } - .map { $0.value } - .skipNil() - } - - /// Do not forward any values from `self` until `predicate` returns false, - /// at which point the returned signal behaves exactly like `signal`. - /// - /// - parameters: - /// - predicate: A closure that accepts a value and returns whether `self` - /// should still not forward that value to a `signal`. - /// - /// - returns: A signal that sends only forwarded values from `self`. - public func skip(while predicate: @escaping (Value) -> Bool) -> Signal { - return Signal { observer in - var shouldSkip = true - - return self.observe { event in - switch event { - case let .value(value): - shouldSkip = shouldSkip && predicate(value) - if !shouldSkip { - fallthrough - } - - case .failed, .completed, .interrupted: - observer.action(event) - } - } - } - } - - /// Forward events from `self` until `replacement` begins sending events. - /// - /// - parameters: - /// - replacement: A signal to wait to wait for values from and start - /// sending them as a replacement to `self`'s values. - /// - /// - returns: A signal which passes through `value`, failed, and - /// `interrupted` events from `self` until `replacement` sends - /// an event, at which point the returned signal will send that - /// event and switch to passing through events from `replacement` - /// instead, regardless of whether `self` has sent events - /// already. - public func take(untilReplacement signal: Signal) -> Signal { - return Signal { observer in - let disposable = CompositeDisposable() - - let signalDisposable = self.observe { event in - switch event { - case .completed: - break - - case .value, .failed, .interrupted: - observer.action(event) - } - } - - disposable += signalDisposable - disposable += signal.observe { event in - signalDisposable?.dispose() - observer.action(event) - } - - return disposable - } - } - - /// Wait until `self` completes and then forward the final `count` values - /// on the returned signal. - /// - /// - parameters: - /// - count: Number of last events to send after `self` completes. - /// - /// - returns: A signal that receives up to `count` values from `self` - /// after `self` completes. - public func take(last count: Int) -> Signal { - return Signal { observer in - var buffer: [Value] = [] - buffer.reserveCapacity(count) - - return self.observe { event in - switch event { - case let .value(value): - // To avoid exceeding the reserved capacity of the buffer, - // we remove then add. Remove elements until we have room to - // add one more. - while (buffer.count + 1) > count { - buffer.remove(at: 0) - } - - buffer.append(value) - case let .failed(error): - observer.send(error: error) - case .completed: - buffer.forEach(observer.send(value:)) - - observer.sendCompleted() - case .interrupted: - observer.sendInterrupted() - } - } - } - } - - /// Forward any values from `self` until `predicate` returns false, at which - /// point the returned signal will complete. - /// - /// - parameters: - /// - predicate: A closure that accepts value and returns `Bool` value - /// whether `self` should forward it to `signal` and continue - /// sending other events. - /// - /// - returns: A signal that sends events until the values sent by `self` - /// pass the given `predicate`. - public func take(while predicate: @escaping (Value) -> Bool) -> Signal { - return Signal { observer in - return self.observe { event in - if let value = event.value, !predicate(value) { - observer.sendCompleted() - } else { - observer.action(event) - } - } - } - } -} - -private struct ZipState { - var values: (left: [Left], right: [Right]) = ([], []) - var isCompleted: (left: Bool, right: Bool) = (false, false) - - var isFinished: Bool { - return (isCompleted.left && values.left.isEmpty) || (isCompleted.right && values.right.isEmpty) - } -} - -extension SignalProtocol { - /// Zip elements of two signals into pairs. The elements of any Nth pair - /// are the Nth elements of the two input signals. - /// - /// - parameters: - /// - otherSignal: A signal to zip values with. - /// - /// - returns: A signal that sends tuples of `self` and `otherSignal`. - public func zip(with other: Signal) -> Signal<(Value, U), Error> { - return Signal { observer in - let state = Atomic(ZipState()) - let disposable = CompositeDisposable() - - let flush = { - var tuple: (Value, U)? - var isFinished = false - - state.modify { state in - guard !state.values.left.isEmpty && !state.values.right.isEmpty else { - isFinished = state.isFinished - return - } - - tuple = (state.values.left.removeFirst(), state.values.right.removeFirst()) - isFinished = state.isFinished - } - - if let tuple = tuple { - observer.send(value: tuple) - } - - if isFinished { - observer.sendCompleted() - } - } - - let onFailed = observer.send(error:) - let onInterrupted = observer.sendInterrupted - - disposable += self.observe { event in - switch event { - case let .value(value): - state.modify { - $0.values.left.append(value) - } - flush() - - case let .failed(error): - onFailed(error) - - case .completed: - state.modify { - $0.isCompleted.left = true - } - flush() - - case .interrupted: - onInterrupted() - } - } - - disposable += other.observe { event in - switch event { - case let .value(value): - state.modify { - $0.values.right.append(value) - } - flush() - - case let .failed(error): - onFailed(error) - - case .completed: - state.modify { - $0.isCompleted.right = true - } - flush() - - case .interrupted: - onInterrupted() - } - } - - return disposable - } - } - - /// Forward the latest value on `scheduler` after at least `interval` - /// seconds have passed since *the returned signal* last sent a value. - /// - /// If `self` always sends values more frequently than `interval` seconds, - /// then the returned signal will send a value every `interval` seconds. - /// - /// To measure from when `self` last sent a value, see `debounce`. - /// - /// - seealso: `debounce` - /// - /// - note: If multiple values are received before the interval has elapsed, - /// the latest value is the one that will be passed on. - /// - /// - note: If `self` terminates while a value is being throttled, that - /// value will be discarded and the returned signal will terminate - /// immediately. - /// - /// - note: If the device time changed backwards before previous date while - /// a value is being throttled, and if there is a new value sent, - /// the new value will be passed anyway. - /// - /// - parameters: - /// - interval: Number of seconds to wait between sent values. - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A signal that sends values at least `interval` seconds - /// appart on a given scheduler. - public func throttle(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { - precondition(interval >= 0) - - return Signal { observer in - let state: Atomic> = Atomic(ThrottleState()) - let schedulerDisposable = SerialDisposable() - - let disposable = CompositeDisposable() - disposable += schedulerDisposable - - disposable += self.observe { event in - guard let value = event.value else { - schedulerDisposable.inner = scheduler.schedule { - observer.action(event) - } - return - } - - var scheduleDate: Date! - state.modify { - $0.pendingValue = value - - let proposedScheduleDate: Date - if let previousDate = $0.previousDate, previousDate.compare(scheduler.currentDate) != .orderedDescending { - proposedScheduleDate = previousDate.addingTimeInterval(interval) - } else { - proposedScheduleDate = scheduler.currentDate - } - - switch proposedScheduleDate.compare(scheduler.currentDate) { - case .orderedAscending: - scheduleDate = scheduler.currentDate - - case .orderedSame: fallthrough - case .orderedDescending: - scheduleDate = proposedScheduleDate - } - } - - schedulerDisposable.inner = scheduler.schedule(after: scheduleDate) { - let pendingValue: Value? = state.modify { state in - defer { - if state.pendingValue != nil { - state.pendingValue = nil - state.previousDate = scheduleDate - } - } - return state.pendingValue - } - - if let pendingValue = pendingValue { - observer.send(value: pendingValue) - } - } - } - - return disposable - } - } - - /// Conditionally throttles values sent on the receiver whenever - /// `shouldThrottle` is true, forwarding values on the given scheduler. - /// - /// - note: While `shouldThrottle` remains false, values are forwarded on the - /// given scheduler. If multiple values are received while - /// `shouldThrottle` is true, the latest value is the one that will - /// be passed on. - /// - /// - note: If the input signal terminates while a value is being throttled, - /// that value will be discarded and the returned signal will - /// terminate immediately. - /// - /// - note: If `shouldThrottle` completes before the receiver, and its last - /// value is `true`, the returned signal will remain in the throttled - /// state, emitting no further values until it terminates. - /// - /// - parameters: - /// - shouldThrottle: A boolean property that controls whether values - /// should be throttled. - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A signal that sends values only while `shouldThrottle` is false. - public func throttle(while shouldThrottle: P, on scheduler: Scheduler) -> Signal - where P.Value == Bool - { - return Signal { observer in - let initial: ThrottleWhileState = .resumed - let state = Atomic(initial) - let schedulerDisposable = SerialDisposable() - - let disposable = CompositeDisposable() - disposable += schedulerDisposable - - disposable += shouldThrottle.producer - .skipRepeats() - .startWithValues { shouldThrottle in - let valueToSend = state.modify { state -> Value? in - guard !state.isTerminated else { return nil } - - if shouldThrottle { - state = .throttled(nil) - } else { - defer { state = .resumed } - - if case let .throttled(value?) = state { - return value - } - } - - return nil - } - - if let value = valueToSend { - schedulerDisposable.inner = scheduler.schedule { - observer.send(value: value) - } - } - } - - disposable += self.observe { event in - let eventToSend = state.modify { state -> Event? in - switch event { - case let .value(value): - switch state { - case .throttled: - state = .throttled(value) - return nil - case .resumed: - return event - case .terminated: - return nil - } - - case .completed, .interrupted, .failed: - state = .terminated - return event - } - } - - if let event = eventToSend { - schedulerDisposable.inner = scheduler.schedule { - observer.action(event) - } - } - } - - return disposable - } - } - - /// Forward the latest value on `scheduler` after at least `interval` - /// seconds have passed since `self` last sent a value. - /// - /// If `self` always sends values more frequently than `interval` seconds, - /// then the returned signal will never send any values. - /// - /// To measure from when the *returned signal* last sent a value, see - /// `throttle`. - /// - /// - seealso: `throttle` - /// - /// - note: If multiple values are received before the interval has elapsed, - /// the latest value is the one that will be passed on. - /// - /// - note: If the input signal terminates while a value is being debounced, - /// that value will be discarded and the returned signal will - /// terminate immediately. - /// - /// - parameters: - /// - interval: A number of seconds to wait before sending a value. - /// - scheduler: A scheduler to send values on. - /// - /// - returns: A signal that sends values that are sent from `self` at least - /// `interval` seconds apart. - public func debounce(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { - precondition(interval >= 0) - - let d = SerialDisposable() - - return Signal { observer in - return self.observe { event in - switch event { - case let .value(value): - let date = scheduler.currentDate.addingTimeInterval(interval) - d.inner = scheduler.schedule(after: date) { - observer.send(value: value) - } - - case .completed, .failed, .interrupted: - d.inner = scheduler.schedule { - observer.action(event) - } - } - } - } - } -} - -extension SignalProtocol { - /// Forward only those values from `self` that have unique identities across - /// the set of all values that have been seen. - /// - /// - note: This causes the identities to be retained to check for - /// uniqueness. - /// - /// - parameters: - /// - transform: A closure that accepts a value and returns identity - /// value. - /// - /// - returns: A signal that sends unique values during its lifetime. - public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> Signal { - return Signal { observer in - var seenValues: Set = [] - - return self - .observe { event in - switch event { - case let .value(value): - let identity = transform(value) - if !seenValues.contains(identity) { - seenValues.insert(identity) - fallthrough - } - - case .failed, .completed, .interrupted: - observer.action(event) - } - } - } - } -} - -extension SignalProtocol where Value: Hashable { - /// Forward only those values from `self` that are unique across the set of - /// all values that have been seen. - /// - /// - note: This causes the values to be retained to check for uniqueness. - /// Providing a function that returns a unique value for each sent - /// value can help you reduce the memory footprint. - /// - /// - returns: A signal that sends unique values during its lifetime. - public func uniqueValues() -> Signal { - return uniqueValues { $0 } - } -} - -private struct ThrottleState { - var previousDate: Date? = nil - var pendingValue: Value? = nil -} - -private enum ThrottleWhileState { - case resumed - case throttled(Value?) - case terminated - - var isTerminated: Bool { - switch self { - case .terminated: - return true - case .resumed, .throttled: - return false - } - } -} - -extension SignalProtocol { - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal) -> Signal<(Value, B), Error> { - return a.combineLatest(with: b) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal) -> Signal<(Value, B, C), Error> { - return combineLatest(a, b) - .combineLatest(with: c) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(Value, B, C, D), Error> { - return combineLatest(a, b, c) - .combineLatest(with: d) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(Value, B, C, D, E), Error> { - return combineLatest(a, b, c, d) - .combineLatest(with: e) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(Value, B, C, D, E, F), Error> { - return combineLatest(a, b, c, d, e) - .combineLatest(with: f) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(Value, B, C, D, E, F, G), Error> { - return combineLatest(a, b, c, d, e, f) - .combineLatest(with: g) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(Value, B, C, D, E, F, G, H), Error> { - return combineLatest(a, b, c, d, e, f, g) - .combineLatest(with: h) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I), Error> { - return combineLatest(a, b, c, d, e, f, g, h) - .combineLatest(with: i) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I, J), Error> { - return combineLatest(a, b, c, d, e, f, g, h, i) - .combineLatest(with: j) - .map(repack) - } - - /// Combines the values of all the given signals, in the manner described by - /// `combineLatest(with:)`. No events will be sent if the sequence is empty. - public static func combineLatest(_ signals: S) -> Signal<[Value], Error> - where S.Iterator.Element == Signal - { - var generator = signals.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { signal, next in - signal.combineLatest(with: next).map { $0.0 + [$0.1] } - } - } - - return .never - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal) -> Signal<(Value, B), Error> { - return a.zip(with: b) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal) -> Signal<(Value, B, C), Error> { - return zip(a, b) - .zip(with: c) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(Value, B, C, D), Error> { - return zip(a, b, c) - .zip(with: d) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(Value, B, C, D, E), Error> { - return zip(a, b, c, d) - .zip(with: e) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(Value, B, C, D, E, F), Error> { - return zip(a, b, c, d, e) - .zip(with: f) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(Value, B, C, D, E, F, G), Error> { - return zip(a, b, c, d, e, f) - .zip(with: g) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(Value, B, C, D, E, F, G, H), Error> { - return zip(a, b, c, d, e, f, g) - .zip(with: h) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I), Error> { - return zip(a, b, c, d, e, f, g, h) - .zip(with: i) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. - public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I, J), Error> { - return zip(a, b, c, d, e, f, g, h, i) - .zip(with: j) - .map(repack) - } - - /// Zips the values of all the given signals, in the manner described by - /// `zipWith`. No events will be sent if the sequence is empty. - public static func zip(_ signals: S) -> Signal<[Value], Error> - where S.Iterator.Element == Signal - { - var generator = signals.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { signal, next in - signal.zip(with: next).map { $0.0 + [$0.1] } - } - } - - return .never - } -} - -extension SignalProtocol { - /// Forward events from `self` until `interval`. Then if signal isn't - /// completed yet, fails with `error` on `scheduler`. - /// - /// - note: If the interval is 0, the timeout will be scheduled immediately. - /// The signal must complete synchronously (or on a faster - /// scheduler) to avoid the timeout. - /// - /// - parameters: - /// - error: Error to send with failed event if `self` is not completed - /// when `interval` passes. - /// - interval: Number of seconds to wait for `self` to complete. - /// - scheudler: A scheduler to deliver error on. - /// - /// - returns: A signal that sends events for at most `interval` seconds, - /// then, if not `completed` - sends `error` with failed event - /// on `scheduler`. - public func timeout(after interval: TimeInterval, raising error: Error, on scheduler: DateScheduler) -> Signal { - precondition(interval >= 0) - - return Signal { observer in - let disposable = CompositeDisposable() - let date = scheduler.currentDate.addingTimeInterval(interval) - - disposable += scheduler.schedule(after: date) { - observer.send(error: error) - } - - disposable += self.observe(observer) - return disposable - } - } -} - -extension SignalProtocol where Error == NoError { - /// Promote a signal that does not generate failures into one that can. - /// - /// - note: This does not actually cause failures to be generated for the - /// given signal, but makes it easier to combine with other signals - /// that may fail; for example, with operators like - /// `combineLatestWith`, `zipWith`, `flatten`, etc. - /// - /// - parameters: - /// - _ An `ErrorType`. - /// - /// - returns: A signal that has an instantiatable `ErrorType`. - public func promoteErrors(_: F.Type) -> Signal { - return Signal { observer in - return self.observe { event in - switch event { - case let .value(value): - observer.send(value: value) - case .failed: - fatalError("NoError is impossible to construct") - case .completed: - observer.sendCompleted() - case .interrupted: - observer.sendInterrupted() - } - } - } - } - - /// Forward events from `self` until `interval`. Then if signal isn't - /// completed yet, fails with `error` on `scheduler`. - /// - /// - note: If the interval is 0, the timeout will be scheduled immediately. - /// The signal must complete synchronously (or on a faster - /// scheduler) to avoid the timeout. - /// - /// - parameters: - /// - interval: Number of seconds to wait for `self` to complete. - /// - error: Error to send with `failed` event if `self` is not completed - /// when `interval` passes. - /// - scheudler: A scheduler to deliver error on. - /// - /// - returns: A signal that sends events for at most `interval` seconds, - /// then, if not `completed` - sends `error` with `failed` event - /// on `scheduler`. - public func timeout( - after interval: TimeInterval, - raising error: NewError, - on scheduler: DateScheduler - ) -> Signal { - return self - .promoteErrors(NewError.self) - .timeout(after: interval, raising: error, on: scheduler) - } -} - -extension SignalProtocol where Value == Bool { - /// Create a signal that computes a logical NOT in the latest values of `self`. - /// - /// - returns: A signal that emits the logical NOT results. - public var negated: Signal { - return self.map(!) - } - - /// Create a signal that computes a logical AND between the latest values of `self` - /// and `signal`. - /// - /// - parameters: - /// - signal: Signal to be combined with `self`. - /// - /// - returns: A signal that emits the logical AND results. - public func and(_ signal: Signal) -> Signal { - return self.combineLatest(with: signal).map { $0 && $1 } - } - - /// Create a signal that computes a logical OR between the latest values of `self` - /// and `signal`. - /// - /// - parameters: - /// - signal: Signal to be combined with `self`. - /// - /// - returns: A signal that emits the logical OR results. - public func or(_ signal: Signal) -> Signal { - return self.combineLatest(with: signal).map { $0 || $1 } - } -} - -extension SignalProtocol { - /// Apply `operation` to values from `self` with `success`ful results - /// forwarded on the returned signal and `failure`s sent as failed events. - /// - /// - parameters: - /// - operation: A closure that accepts a value and returns a `Result`. - /// - /// - returns: A signal that receives `success`ful `Result` as `value` event - /// and `failure` as failed event. - public func attempt(_ operation: @escaping (Value) -> Result<(), Error>) -> Signal { - return attemptMap { value in - return operation(value).map { - return value - } - } - } - - /// Apply `operation` to values from `self` with `success`ful results mapped - /// on the returned signal and `failure`s sent as failed events. - /// - /// - parameters: - /// - operation: A closure that accepts a value and returns a result of - /// a mapped value as `success`. - /// - /// - returns: A signal that sends mapped values from `self` if returned - /// `Result` is `success`ful, `failed` events otherwise. - public func attemptMap(_ operation: @escaping (Value) -> Result) -> Signal { - return Signal { observer in - self.observe { event in - switch event { - case let .value(value): - operation(value).analysis( - ifSuccess: observer.send(value:), - ifFailure: observer.send(error:) - ) - case let .failed(error): - observer.send(error: error) - case .completed: - observer.sendCompleted() - case .interrupted: - observer.sendInterrupted() - } - } - } - } -} - -extension SignalProtocol where Error == NoError { - /// Apply a failable `operation` to values from `self` with successful - /// results forwarded on the returned signal and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value. - /// - /// - returns: A signal that forwards successes as `value` events and thrown - /// errors as `failed` events. - public func attempt(_ operation: @escaping (Value) throws -> Void) -> Signal { - return self - .promoteErrors(AnyError.self) - .attempt(operation) - } - - /// Apply a failable `operation` to values from `self` with successful - /// results mapped on the returned signal and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value and attempts to - /// transform it. - /// - /// - returns: A signal that sends successfully mapped values from `self`, or - /// thrown errors as `failed` events. - public func attemptMap(_ operation: @escaping (Value) throws -> U) -> Signal { - return self - .promoteErrors(AnyError.self) - .attemptMap(operation) - } -} - -extension SignalProtocol where Error == AnyError { - /// Apply a failable `operation` to values from `self` with successful - /// results forwarded on the returned signal and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value. - /// - /// - returns: A signal that forwards successes as `value` events and thrown - /// errors as `failed` events. - public func attempt(_ operation: @escaping (Value) throws -> Void) -> Signal { - return attemptMap { value in - try operation(value) - return value - } - } - - /// Apply a failable `operation` to values from `self` with successful - /// results mapped on the returned signal and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value and attempts to - /// transform it. - /// - /// - returns: A signal that sends successfully mapped values from `self`, or - /// thrown errors as `failed` events. - public func attemptMap(_ operation: @escaping (Value) throws -> U) -> Signal { - return attemptMap { value in - ReactiveSwift.materialize { - try operation(value) - } - } - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/SignalProducer.swift b/Example/Pods/ReactiveSwift/Sources/SignalProducer.swift deleted file mode 100644 index 3e7be40..0000000 --- a/Example/Pods/ReactiveSwift/Sources/SignalProducer.swift +++ /dev/null @@ -1,2184 +0,0 @@ -import Dispatch -import Foundation -import Result - -/// A SignalProducer creates Signals that can produce values of type `Value` -/// and/or fail with errors of type `Error`. If no failure should be possible, -/// `NoError` can be specified for `Error`. -/// -/// SignalProducers can be used to represent operations or tasks, like network -/// requests, where each invocation of `start()` will create a new underlying -/// operation. This ensures that consumers will receive the results, versus a -/// plain Signal, where the results might be sent before any observers are -/// attached. -/// -/// Because of the behavior of `start()`, different Signals created from the -/// producer may see a different version of Events. The Events may arrive in a -/// different order between Signals, or the stream might be completely -/// different! -public struct SignalProducer { - public typealias ProducedSignal = Signal - - private let startHandler: (Signal.Observer, CompositeDisposable) -> Void - - /// Initializes a `SignalProducer` that will emit the same events as the - /// given signal. - /// - /// If the Disposable returned from `start()` is disposed or a terminating - /// event is sent to the observer, the given signal will be disposed. - /// - /// - parameters: - /// - signal: A signal to observe after starting the producer. - public init(_ signal: S) where S.Value == Value, S.Error == Error { - self.init { observer, disposable in - disposable += signal.observe(observer) - } - } - - /// Initializes a SignalProducer that will invoke the given closure once for - /// each invocation of `start()`. - /// - /// The events that the closure puts into the given observer will become - /// the events sent by the started `Signal` to its observers. - /// - /// - note: If the `Disposable` returned from `start()` is disposed or a - /// terminating event is sent to the observer, the given - /// `CompositeDisposable` will be disposed, at which point work - /// should be interrupted and any temporary resources cleaned up. - /// - /// - parameters: - /// - startHandler: A closure that accepts observer and a disposable. - public init(_ startHandler: @escaping (Signal.Observer, CompositeDisposable) -> Void) { - self.startHandler = startHandler - } - - /// Creates a producer for a `Signal` that will immediately send one value - /// then complete. - /// - /// - parameters: - /// - value: A value that should be sent by the `Signal` in a `value` - /// event. - public init(value: Value) { - self.init { observer, disposable in - observer.send(value: value) - observer.sendCompleted() - } - } - - /// Creates a producer for a `Signal` that immediately sends one value, then - /// completes. - /// - /// This initializer differs from `init(value:)` in that its sole `value` - /// event is constructed lazily by invoking the supplied `action` when - /// the `SignalProducer` is started. - /// - /// - parameters: - /// - action: A action that yields a value to be sent by the `Signal` as - /// a `value` event. - public init(_ action: @escaping () -> Value) { - self.init { observer, disposable in - observer.send(value: action()) - observer.sendCompleted() - } - } - - /// Creates a producer for a `Signal` that will immediately fail with the - /// given error. - /// - /// - parameters: - /// - error: An error that should be sent by the `Signal` in a `failed` - /// event. - public init(error: Error) { - self.init { observer, disposable in - observer.send(error: error) - } - } - - /// Creates a producer for a Signal that will immediately send one value - /// then complete, or immediately fail, depending on the given Result. - /// - /// - parameters: - /// - result: A `Result` instance that will send either `value` event if - /// `result` is `success`ful or `failed` event if `result` is a - /// `failure`. - public init(result: Result) { - switch result { - case let .success(value): - self.init(value: value) - - case let .failure(error): - self.init(error: error) - } - } - - /// Creates a producer for a Signal that will immediately send the values - /// from the given sequence, then complete. - /// - /// - parameters: - /// - values: A sequence of values that a `Signal` will send as separate - /// `value` events and then complete. - public init(_ values: S) where S.Iterator.Element == Value { - self.init { observer, disposable in - for value in values { - observer.send(value: value) - - if disposable.isDisposed { - break - } - } - - observer.sendCompleted() - } - } - - /// Creates a producer for a Signal that will immediately send the values - /// from the given sequence, then complete. - /// - /// - parameters: - /// - first: First value for the `Signal` to send. - /// - second: Second value for the `Signal` to send. - /// - tail: Rest of the values to be sent by the `Signal`. - public init(values first: Value, _ second: Value, _ tail: Value...) { - self.init([ first, second ] + tail) - } - - /// A producer for a Signal that will immediately complete without sending - /// any values. - public static var empty: SignalProducer { - return self.init { observer, disposable in - observer.sendCompleted() - } - } - - /// A producer for a Signal that never sends any events to its observers. - public static var never: SignalProducer { - return self.init { _ in return } - } - - /// Create a Signal from the producer, pass it into the given closure, - /// then start sending events on the Signal when the closure has returned. - /// - /// The closure will also receive a disposable which can be used to - /// interrupt the work associated with the signal and immediately send an - /// `interrupted` event. - /// - /// - parameters: - /// - setUp: A closure that accepts a `signal` and `interrupter`. - public func startWithSignal(_ setup: (_ signal: Signal, _ interrupter: Disposable) -> Void) { - // Disposes of the work associated with the SignalProducer and any - // upstream producers. - let producerDisposable = CompositeDisposable() - - let (signal, observer) = Signal.pipe(disposable: producerDisposable) - - // Directly disposed of when `start()` or `startWithSignal()` is - // disposed. - let cancelDisposable = ActionDisposable(action: observer.sendInterrupted) - - setup(signal, cancelDisposable) - - if cancelDisposable.isDisposed { - return - } - - startHandler(observer, producerDisposable) - } -} - -/// A protocol used to constraint `SignalProducer` operators. -public protocol SignalProducerProtocol { - /// The type of values being sent on the producer - associatedtype Value - /// The type of error that can occur on the producer. If errors aren't possible - /// then `NoError` can be used. - associatedtype Error: Swift.Error - - /// Extracts a signal producer from the receiver. - var producer: SignalProducer { get } - - /// Initialize a signal - init(_ startHandler: @escaping (Signal.Observer, CompositeDisposable) -> Void) - - /// Creates a Signal from the producer, passes it into the given closure, - /// then starts sending events on the Signal when the closure has returned. - func startWithSignal(_ setup: (_ signal: Signal, _ interrupter: Disposable) -> Void) -} - -extension SignalProducer: SignalProducerProtocol { - public var producer: SignalProducer { - return self - } -} - -extension SignalProducerProtocol { - /// Create a Signal from the producer, then attach the given observer to - /// the `Signal` as an observer. - /// - /// - parameters: - /// - observer: An observer to attach to produced signal. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the signal and immediately send an - /// `interrupted` event. - @discardableResult - public func start(_ observer: Signal.Observer = .init()) -> Disposable { - var disposable: Disposable! - - startWithSignal { signal, innerDisposable in - signal.observe(observer) - disposable = innerDisposable - } - - return disposable - } - - /// Convenience override for start(_:) to allow trailing-closure style - /// invocations. - /// - /// - parameters: - /// - observerAction: A closure that accepts `Event` sent by the produced - /// signal. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the signal and immediately send an - /// `interrupted` event. - @discardableResult - public func start(_ observerAction: @escaping Signal.Observer.Action) -> Disposable { - return start(Observer(observerAction)) - } - - /// Create a Signal from the producer, then add an observer to the `Signal`, - /// which will invoke the given callback when `value` or `failed` events are - /// received. - /// - /// - parameters: - /// - result: A closure that accepts a `result` that contains a `.success` - /// case for `value` events or `.failure` case for `failed` event. - /// - /// - returns: A Disposable which can be used to interrupt the work - /// associated with the Signal, and prevent any future callbacks - /// from being invoked. - @discardableResult - public func startWithResult(_ result: @escaping (Result) -> Void) -> Disposable { - return start( - Observer( - value: { result(.success($0)) }, - failed: { result(.failure($0)) } - ) - ) - } - - /// Create a Signal from the producer, then add exactly one observer to the - /// Signal, which will invoke the given callback when a `completed` event is - /// received. - /// - /// - parameters: - /// - completed: A closure that will be envoked when produced signal sends - /// `completed` event. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the signal. - @discardableResult - public func startWithCompleted(_ completed: @escaping () -> Void) -> Disposable { - return start(Observer(completed: completed)) - } - - /// Creates a Signal from the producer, then adds exactly one observer to - /// the Signal, which will invoke the given callback when a `failed` event - /// is received. - /// - /// - parameters: - /// - failed: A closure that accepts an error object. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the signal. - @discardableResult - public func startWithFailed(_ failed: @escaping (Error) -> Void) -> Disposable { - return start(Observer(failed: failed)) - } - - /// Creates a Signal from the producer, then adds exactly one observer to - /// the Signal, which will invoke the given callback when an `interrupted` - /// event is received. - /// - /// - parameters: - /// - interrupted: A closure that is invoked when `interrupted` event is - /// received. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the signal. - @discardableResult - public func startWithInterrupted(_ interrupted: @escaping () -> Void) -> Disposable { - return start(Observer(interrupted: interrupted)) - } - - /// Creates a `Signal` from the producer. - /// - /// This is equivalent to `SignalProducer.startWithSignal`, but it has - /// the downside that any values emitted synchronously upon starting will - /// be missed by the observer, because it won't be able to subscribe in time. - /// That's why we don't want this method to be exposed as `public`, - /// but it's useful internally. - internal func startAndRetrieveSignal() -> Signal { - var result: Signal! - self.startWithSignal { signal, _ in - result = signal - } - - return result - } -} - -extension SignalProducerProtocol where Error == NoError { - /// Create a Signal from the producer, then add exactly one observer to - /// the Signal, which will invoke the given callback when `value` events are - /// received. - /// - /// - parameters: - /// - value: A closure that accepts a value carried by `value` event. - /// - /// - returns: A `Disposable` which can be used to interrupt the work - /// associated with the Signal, and prevent any future callbacks - /// from being invoked. - @discardableResult - public func startWithValues(_ value: @escaping (Value) -> Void) -> Disposable { - return start(Observer(value: value)) - } -} - -extension SignalProducerProtocol { - /// Lift an unary Signal operator to operate upon SignalProducers instead. - /// - /// In other words, this will create a new `SignalProducer` which will apply - /// the given `Signal` operator to _every_ created `Signal`, just as if the - /// operator had been applied to each `Signal` yielded from `start()`. - /// - /// - parameters: - /// - transform: An unary operator to lift. - /// - /// - returns: A signal producer that applies signal's operator to every - /// created signal. - public func lift(_ transform: @escaping (Signal) -> Signal) -> SignalProducer { - return SignalProducer { observer, outerDisposable in - self.startWithSignal { signal, innerDisposable in - outerDisposable += innerDisposable - - transform(signal).observe(observer) - } - } - } - - - /// Lift a binary Signal operator to operate upon SignalProducers instead. - /// - /// In other words, this will create a new `SignalProducer` which will apply - /// the given `Signal` operator to _every_ `Signal` created from the two - /// producers, just as if the operator had been applied to each `Signal` - /// yielded from `start()`. - /// - /// - note: starting the returned producer will start the receiver of the - /// operator, which may not be adviseable for some operators. - /// - /// - parameters: - /// - transform: A binary operator to lift. - /// - /// - returns: A binary operator that operates on two signal producers. - public func lift(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { - return liftRight(transform) - } - - /// Right-associative lifting of a binary signal operator over producers. - /// That is, the argument producer will be started before the receiver. When - /// both producers are synchronous this order can be important depending on - /// the operator to generate correct results. - private func liftRight(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { - return { otherProducer in - return SignalProducer { observer, outerDisposable in - self.startWithSignal { signal, disposable in - outerDisposable.add(disposable) - - otherProducer.startWithSignal { otherSignal, otherDisposable in - outerDisposable += otherDisposable - - transform(signal)(otherSignal).observe(observer) - } - } - } - } - } - - /// Left-associative lifting of a binary signal operator over producers. - /// That is, the receiver will be started before the argument producer. When - /// both producers are synchronous this order can be important depending on - /// the operator to generate correct results. - fileprivate func liftLeft(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { - return { otherProducer in - return SignalProducer { observer, outerDisposable in - otherProducer.startWithSignal { otherSignal, otherDisposable in - outerDisposable += otherDisposable - - self.startWithSignal { signal, disposable in - outerDisposable.add(disposable) - - transform(signal)(otherSignal).observe(observer) - } - } - } - } - } - - /// Lift a binary Signal operator to operate upon a Signal and a - /// SignalProducer instead. - /// - /// In other words, this will create a new `SignalProducer` which will apply - /// the given `Signal` operator to _every_ `Signal` created from the two - /// producers, just as if the operator had been applied to each `Signal` - /// yielded from `start()`. - /// - /// - parameters: - /// - transform: A binary operator to lift. - /// - /// - returns: A binary operator that works on `Signal` and returns - /// `SignalProducer`. - public func lift(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (Signal) -> SignalProducer { - return { otherSignal in - return self.liftRight(transform)(SignalProducer(otherSignal)) - } - } - - /// Map each value in the producer to a new value. - /// - /// - parameters: - /// - transform: A closure that accepts a value and returns a different - /// value. - /// - /// - returns: A signal producer that, when started, will send a mapped - /// value of `self.` - public func map(_ transform: @escaping (Value) -> U) -> SignalProducer { - return lift { $0.map(transform) } - } - - /// Map errors in the producer to a new error. - /// - /// - parameters: - /// - transform: A closure that accepts an error object and returns a - /// different error. - /// - /// - returns: A producer that emits errors of new type. - public func mapError(_ transform: @escaping (Error) -> F) -> SignalProducer { - return lift { $0.mapError(transform) } - } - - /// Maps each value in the producer to a new value, lazily evaluating the - /// supplied transformation on the specified scheduler. - /// - /// - important: Unlike `map`, there is not a 1-1 mapping between incoming - /// values, and values sent on the returned producer. If - /// `scheduler` has not yet scheduled `transform` for - /// execution, then each new value will replace the last one as - /// the parameter to `transform` once it is finally executed. - /// - /// - parameters: - /// - transform: The closure used to obtain the returned value from this - /// producer's underlying value. - /// - /// - returns: A producer that, when started, sends values obtained using - /// `transform` as this producer sends values. - public func lazyMap(on scheduler: Scheduler, transform: @escaping (Value) -> U) -> SignalProducer { - return lift { $0.lazyMap(on: scheduler, transform: transform) } - } - - /// Preserve only the values of the producer that pass the given predicate. - /// - /// - parameters: - /// - predicate: A closure that accepts value and returns `Bool` denoting - /// whether value has passed the test. - /// - /// - returns: A producer that, when started, will send only the values - /// passing the given predicate. - public func filter(_ predicate: @escaping (Value) -> Bool) -> SignalProducer { - return lift { $0.filter(predicate) } - } - - /// Applies `transform` to values from the producer and forwards values with non `nil` results unwrapped. - /// - parameters: - /// - transform: A closure that accepts a value from the `value` event and - /// returns a new optional value. - /// - /// - returns: A producer that will send new values, that are non `nil` after the transformation. - public func filterMap(_ transform: @escaping (Value) -> U?) -> SignalProducer { - return lift { $0.filterMap(transform) } - } - - /// Yield the first `count` values from the input producer. - /// - /// - precondition: `count` must be non-negative number. - /// - /// - parameters: - /// - count: A number of values to take from the signal. - /// - /// - returns: A producer that, when started, will yield the first `count` - /// values from `self`. - public func take(first count: Int) -> SignalProducer { - return lift { $0.take(first: count) } - } - - /// Yield an array of values when `self` completes. - /// - /// - note: When `self` completes without collecting any value, it will send - /// an empty array of values. - /// - /// - returns: A producer that, when started, will yield an array of values - /// when `self` completes. - public func collect() -> SignalProducer<[Value], Error> { - return lift { $0.collect() } - } - - /// Yield an array of values until it reaches a certain count. - /// - /// - precondition: `count` should be greater than zero. - /// - /// - note: When the count is reached the array is sent and the signal - /// starts over yielding a new array of values. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not have `count` values. Alternatively, if were - /// not collected any values will sent an empty array of values. - /// - /// - returns: A producer that, when started, collects at most `count` - /// values from `self`, forwards them as a single array and - /// completes. - public func collect(count: Int) -> SignalProducer<[Value], Error> { - precondition(count > 0) - return lift { $0.collect(count: count) } - } - - /// Yield an array of values based on a predicate which matches the values - /// collected. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not match `predicate`. Alternatively, if were not - /// collected any values will sent an empty array of values. - /// - /// ```` - /// let (producer, observer) = SignalProducer.buffer(1) - /// - /// producer - /// .collect { values in values.reduce(0, combine: +) == 8 } - /// .startWithValues { print($0) } - /// - /// observer.send(value: 1) - /// observer.send(value: 3) - /// observer.send(value: 4) - /// observer.send(value: 7) - /// observer.send(value: 1) - /// observer.send(value: 5) - /// observer.send(value: 6) - /// observer.sendCompleted() - /// - /// // Output: - /// // [1, 3, 4] - /// // [7, 1] - /// // [5, 6] - /// ```` - /// - /// - parameters: - /// - predicate: Predicate to match when values should be sent (returning - /// `true`) or alternatively when they should be collected - /// (where it should return `false`). The most recent value - /// (`value`) is included in `values` and will be the end of - /// the current array of values if the predicate returns - /// `true`. - /// - /// - returns: A producer that, when started, collects values passing the - /// predicate and, when `self` completes, forwards them as a - /// single array and complets. - public func collect(_ predicate: @escaping (_ values: [Value]) -> Bool) -> SignalProducer<[Value], Error> { - return lift { $0.collect(predicate) } - } - - /// Yield an array of values based on a predicate which matches the values - /// collected and the next value. - /// - /// - note: When `self` completes any remaining values will be sent, the - /// last array may not match `predicate`. Alternatively, if no - /// values were collected an empty array will be sent. - /// - /// ```` - /// let (producer, observer) = SignalProducer.buffer(1) - /// - /// producer - /// .collect { values, value in value == 7 } - /// .startWithValues { print($0) } - /// - /// observer.send(value: 1) - /// observer.send(value: 1) - /// observer.send(value: 7) - /// observer.send(value: 7) - /// observer.send(value: 5) - /// observer.send(value: 6) - /// observer.sendCompleted() - /// - /// // Output: - /// // [1, 1] - /// // [7] - /// // [7, 5, 6] - /// ```` - /// - /// - parameters: - /// - predicate: Predicate to match when values should be sent (returning - /// `true`) or alternatively when they should be collected - /// (where it should return `false`). The most recent value - /// (`vaule`) is not included in `values` and will be the - /// start of the next array of values if the predicate - /// returns `true`. - /// - /// - returns: A signal that will yield an array of values based on a - /// predicate which matches the values collected and the next - /// value. - public func collect(_ predicate: @escaping (_ values: [Value], _ value: Value) -> Bool) -> SignalProducer<[Value], Error> { - return lift { $0.collect(predicate) } - } - - /// Forward all events onto the given scheduler, instead of whichever - /// scheduler they originally arrived upon. - /// - /// - parameters: - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A producer that, when started, will yield `self` values on - /// provided scheduler. - public func observe(on scheduler: Scheduler) -> SignalProducer { - return lift { $0.observe(on: scheduler) } - } - - /// Combine the latest value of the receiver with the latest value from the - /// given producer. - /// - /// - note: The returned producer will not send a value until both inputs - /// have sent at least one value each. - /// - /// - note: If either producer is interrupted, the returned producer will - /// also be interrupted. - /// - /// - note: The returned producer will not complete until both inputs - /// complete. - /// - /// - parameters: - /// - other: A producer to combine `self`'s value with. - /// - /// - returns: A producer that, when started, will yield a tuple containing - /// values of `self` and given producer. - public func combineLatest(with other: SignalProducer) -> SignalProducer<(Value, U), Error> { - return liftLeft(Signal.combineLatest)(other) - } - - /// Combine the latest value of the receiver with the latest value from - /// the given signal. - /// - /// - note: The returned producer will not send a value until both inputs - /// have sent at least one value each. - /// - /// - note: If either input is interrupted, the returned producer will also - /// be interrupted. - /// - /// - note: The returned producer will not complete until both inputs - /// complete. - /// - /// - parameters: - /// - other: A signal to combine `self`'s value with. - /// - /// - returns: A producer that, when started, will yield a tuple containing - /// values of `self` and given signal. - public func combineLatest(with other: Signal) -> SignalProducer<(Value, U), Error> { - return lift(Signal.combineLatest(with:))(other) - } - - /// Delay `value` and `completed` events by the given interval, forwarding - /// them on the given scheduler. - /// - /// - note: `failed` and `interrupted` events are always scheduled - /// immediately. - /// - /// - parameters: - /// - interval: Interval to delay `value` and `completed` events by. - /// - scheduler: A scheduler to deliver delayed events on. - /// - /// - returns: A producer that, when started, will delay `value` and - /// `completed` events and will yield them on given scheduler. - public func delay(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { - return lift { $0.delay(interval, on: scheduler) } - } - - /// Skip the first `count` values, then forward everything afterward. - /// - /// - parameters: - /// - count: A number of values to skip. - /// - /// - returns: A producer that, when started, will skip the first `count` - /// values, then forward everything afterward. - public func skip(first count: Int) -> SignalProducer { - return lift { $0.skip(first: count) } - } - - /// Treats all Events from the input producer as plain values, allowing them - /// to be manipulated just like any other value. - /// - /// In other words, this brings Events “into the monad.” - /// - /// - note: When a Completed or Failed event is received, the resulting - /// producer will send the Event itself and then complete. When an - /// `interrupted` event is received, the resulting producer will - /// send the `Event` itself and then interrupt. - /// - /// - returns: A producer that sends events as its values. - public func materialize() -> SignalProducer, NoError> { - return lift { $0.materialize() } - } - - /// Forward the latest value from `self` with the value from `sampler` as a - /// tuple, only when `sampler` sends a `value` event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - sampler: A producer that will trigger the delivery of `value` event - /// from `self`. - /// - /// - returns: A producer that will send values from `self` and `sampler`, - /// sampled (possibly multiple times) by `sampler`, then complete - /// once both input producers have completed, or interrupt if - /// either input producer is interrupted. - public func sample(with sampler: SignalProducer) -> SignalProducer<(Value, T), Error> { - return liftLeft(Signal.sample(with:))(sampler) - } - - /// Forward the latest value from `self` with the value from `sampler` as a - /// tuple, only when `sampler` sends a `value` event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - sampler: A signal that will trigger the delivery of `value` event - /// from `self`. - /// - /// - returns: A producer that, when started, will send values from `self` - /// and `sampler`, sampled (possibly multiple times) by - /// `sampler`, then complete once both input producers have - /// completed, or interrupt if either input producer is - /// interrupted. - public func sample(with sampler: Signal) -> SignalProducer<(Value, T), Error> { - return lift(Signal.sample(with:))(sampler) - } - - /// Forward the latest value from `self` whenever `sampler` sends a `value` - /// event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - sampler: A producer that will trigger the delivery of `value` event - /// from `self`. - /// - /// - returns: A producer that, when started, will send values from `self`, - /// sampled (possibly multiple times) by `sampler`, then complete - /// once both input producers have completed, or interrupt if - /// either input producer is interrupted. - public func sample(on sampler: SignalProducer<(), NoError>) -> SignalProducer { - return liftLeft(Signal.sample(on:))(sampler) - } - - /// Forward the latest value from `self` whenever `sampler` sends a `value` - /// event. - /// - /// - note: If `sampler` fires before a value has been observed on `self`, - /// nothing happens. - /// - /// - parameters: - /// - trigger: A signal whose `value` or `completed` events will start the - /// deliver of events on `self`. - /// - /// - returns: A producer that will send values from `self`, sampled - /// (possibly multiple times) by `sampler`, then complete once - /// both inputs have completed, or interrupt if either input is - /// interrupted. - public func sample(on sampler: Signal<(), NoError>) -> SignalProducer { - return lift(Signal.sample(on:))(sampler) - } - - /// Forward the latest value from `samplee` with the value from `self` as a - /// tuple, only when `self` sends a `value` event. - /// This is like a flipped version of `sample(with:)`, but `samplee`'s - /// terminal events are completely ignored. - /// - /// - note: If `self` fires before a value has been observed on `samplee`, - /// nothing happens. - /// - /// - parameters: - /// - samplee: A producer whose latest value is sampled by `self`. - /// - /// - returns: A signal that will send values from `self` and `samplee`, - /// sampled (possibly multiple times) by `self`, then terminate - /// once `self` has terminated. **`samplee`'s terminated events - /// are ignored**. - public func withLatest(from samplee: SignalProducer) -> SignalProducer<(Value, U), Error> { - return liftRight(Signal.withLatest)(samplee) - } - - /// Forward the latest value from `samplee` with the value from `self` as a - /// tuple, only when `self` sends a `value` event. - /// This is like a flipped version of `sample(with:)`, but `samplee`'s - /// terminal events are completely ignored. - /// - /// - note: If `self` fires before a value has been observed on `samplee`, - /// nothing happens. - /// - /// - parameters: - /// - samplee: A signal whose latest value is sampled by `self`. - /// - /// - returns: A signal that will send values from `self` and `samplee`, - /// sampled (possibly multiple times) by `self`, then terminate - /// once `self` has terminated. **`samplee`'s terminated events - /// are ignored**. - public func withLatest(from samplee: Signal) -> SignalProducer<(Value, U), Error> { - return lift(Signal.withLatest)(samplee) - } - - /// Forwards events from `self` until `lifetime` ends, at which point the - /// returned producer will complete. - /// - /// - parameters: - /// - lifetime: A lifetime whose `ended` signal will cause the returned - /// producer to complete. - /// - /// - returns: A producer that will deliver events until `lifetime` ends. - public func take(during lifetime: Lifetime) -> SignalProducer { - return lift { $0.take(during: lifetime) } - } - - /// Forward events from `self` until `trigger` sends a `value` or `completed` - /// event, at which point the returned producer will complete. - /// - /// - parameters: - /// - trigger: A producer whose `value` or `completed` events will stop the - /// delivery of `value` events from `self`. - /// - /// - returns: A producer that will deliver events until `trigger` sends - /// `value` or `completed` events. - public func take(until trigger: SignalProducer<(), NoError>) -> SignalProducer { - return liftRight(Signal.take(until:))(trigger) - } - - /// Forward events from `self` until `trigger` sends a `value` or - /// `completed` event, at which point the returned producer will complete. - /// - /// - parameters: - /// - trigger: A signal whose `value` or `completed` events will stop the - /// delivery of `value` events from `self`. - /// - /// - returns: A producer that will deliver events until `trigger` sends - /// `value` or `completed` events. - public func take(until trigger: Signal<(), NoError>) -> SignalProducer { - return lift(Signal.take(until:))(trigger) - } - - /// Do not forward any values from `self` until `trigger` sends a `value` - /// or `completed`, at which point the returned producer behaves exactly - /// like `producer`. - /// - /// - parameters: - /// - trigger: A producer whose `value` or `completed` events will start - /// the deliver of events on `self`. - /// - /// - returns: A producer that will deliver events once the `trigger` sends - /// `value` or `completed` events. - public func skip(until trigger: SignalProducer<(), NoError>) -> SignalProducer { - return liftRight(Signal.skip(until:))(trigger) - } - - /// Do not forward any values from `self` until `trigger` sends a `value` - /// or `completed`, at which point the returned signal behaves exactly like - /// `signal`. - /// - /// - parameters: - /// - trigger: A signal whose `value` or `completed` events will start the - /// deliver of events on `self`. - /// - /// - returns: A producer that will deliver events once the `trigger` sends - /// `value` or `completed` events. - public func skip(until trigger: Signal<(), NoError>) -> SignalProducer { - return lift(Signal.skip(until:))(trigger) - } - - /// Forward events from `self` with history: values of the returned producer - /// are a tuple whose first member is the previous value and whose second - /// member is the current value. `initial` is supplied as the first member - /// when `self` sends its first value. - /// - /// - parameters: - /// - initial: A value that will be combined with the first value sent by - /// `self`. - /// - /// - returns: A producer that sends tuples that contain previous and - /// current sent values of `self`. - public func combinePrevious(_ initial: Value) -> SignalProducer<(Value, Value), Error> { - return lift { $0.combinePrevious(initial) } - } - - /// Send only the final value and then immediately completes. - /// - /// - parameters: - /// - initial: Initial value for the accumulator. - /// - combine: A closure that accepts accumulator and sent value of - /// `self`. - /// - /// - returns: A producer that sends accumulated value after `self` - /// completes. - public func reduce(_ initial: U, _ combine: @escaping (U, Value) -> U) -> SignalProducer { - return lift { $0.reduce(initial, combine) } - } - - /// Aggregate `self`'s values into a single combined value. When `self` - /// emits its first value, `combine` is invoked with `initial` as the first - /// argument and that emitted value as the second argument. The result is - /// emitted from the producer returned from `scan`. That result is then - /// passed to `combine` as the first argument when the next value is - /// emitted, and so on. - /// - /// - parameters: - /// - initial: Initial value for the accumulator. - /// - combine: A closure that accepts accumulator and sent value of - /// `self`. - /// - /// - returns: A producer that sends accumulated value each time `self` - /// emits own value. - public func scan(_ initial: U, _ combine: @escaping (U, Value) -> U) -> SignalProducer { - return lift { $0.scan(initial, combine) } - } - - /// Forward only those values from `self` which do not pass `isRepeat` with - /// respect to the previous value. - /// - /// - note: The first value is always forwarded. - /// - /// - returns: A producer that does not send two equal values sequentially. - public func skipRepeats(_ isRepeat: @escaping (Value, Value) -> Bool) -> SignalProducer { - return lift { $0.skipRepeats(isRepeat) } - } - - /// Do not forward any values from `self` until `predicate` returns false, - /// at which point the returned producer behaves exactly like `self`. - /// - /// - parameters: - /// - predicate: A closure that accepts a value and returns whether `self` - /// should still not forward that value to a `producer`. - /// - /// - returns: A producer that sends only forwarded values from `self`. - public func skip(while predicate: @escaping (Value) -> Bool) -> SignalProducer { - return lift { $0.skip(while: predicate) } - } - - /// Forward events from `self` until `replacement` begins sending events. - /// - /// - parameters: - /// - replacement: A producer to wait to wait for values from and start - /// sending them as a replacement to `self`'s values. - /// - /// - returns: A producer which passes through `value`, `failed`, and - /// `interrupted` events from `self` until `replacement` sends an - /// event, at which point the returned producer will send that - /// event and switch to passing through events from `replacement` - /// instead, regardless of whether `self` has sent events - /// already. - public func take(untilReplacement signal: SignalProducer) -> SignalProducer { - return liftRight(Signal.take(untilReplacement:))(signal) - } - - /// Forwards events from `self` until `replacement` begins sending events. - /// - /// - parameters: - /// - replacement: A signal to wait to wait for values from and start - /// sending them as a replacement to `self`'s values. - /// - /// - returns: A producer which passes through `value`, `failed`, and - /// `interrupted` events from `self` until `replacement` sends an - /// event, at which point the returned producer will send that - /// event and switch to passing through events from `replacement` - /// instead, regardless of whether `self` has sent events - /// already. - public func take(untilReplacement signal: Signal) -> SignalProducer { - return lift(Signal.take(untilReplacement:))(signal) - } - - /// Wait until `self` completes and then forward the final `count` values - /// on the returned producer. - /// - /// - parameters: - /// - count: Number of last events to send after `self` completes. - /// - /// - returns: A producer that receives up to `count` values from `self` - /// after `self` completes. - public func take(last count: Int) -> SignalProducer { - return lift { $0.take(last: count) } - } - - /// Forward any values from `self` until `predicate` returns false, at which - /// point the returned producer will complete. - /// - /// - parameters: - /// - predicate: A closure that accepts value and returns `Bool` value - /// whether `self` should forward it to `signal` and continue - /// sending other events. - /// - /// - returns: A producer that sends events until the values sent by `self` - /// pass the given `predicate`. - public func take(while predicate: @escaping (Value) -> Bool) -> SignalProducer { - return lift { $0.take(while: predicate) } - } - - /// Zip elements of two producers into pairs. The elements of any Nth pair - /// are the Nth elements of the two input producers. - /// - /// - parameters: - /// - other: A producer to zip values with. - /// - /// - returns: A producer that sends tuples of `self` and `otherProducer`. - public func zip(with other: SignalProducer) -> SignalProducer<(Value, U), Error> { - return liftLeft(Signal.zip(with:))(other) - } - - /// Zip elements of this producer and a signal into pairs. The elements of - /// any Nth pair are the Nth elements of the two. - /// - /// - parameters: - /// - other: A signal to zip values with. - /// - /// - returns: A producer that sends tuples of `self` and `otherSignal`. - public func zip(with other: Signal) -> SignalProducer<(Value, U), Error> { - return lift(Signal.zip(with:))(other) - } - - /// Apply `operation` to values from `self` with `success`ful results - /// forwarded on the returned producer and `failure`s sent as `failed` - /// events. - /// - /// - parameters: - /// - operation: A closure that accepts a value and returns a `Result`. - /// - /// - returns: A producer that receives `success`ful `Result` as `value` - /// event and `failure` as `failed` event. - public func attempt(operation: @escaping (Value) -> Result<(), Error>) -> SignalProducer { - return lift { $0.attempt(operation) } - } - - /// Apply `operation` to values from `self` with `success`ful results - /// mapped on the returned producer and `failure`s sent as `failed` events. - /// - /// - parameters: - /// - operation: A closure that accepts a value and returns a result of - /// a mapped value as `success`. - /// - /// - returns: A producer that sends mapped values from `self` if returned - /// `Result` is `success`ful, `failed` events otherwise. - public func attemptMap(_ operation: @escaping (Value) -> Result) -> SignalProducer { - return lift { $0.attemptMap(operation) } - } - - /// Forward the latest value on `scheduler` after at least `interval` - /// seconds have passed since *the returned signal* last sent a value. - /// - /// If `self` always sends values more frequently than `interval` seconds, - /// then the returned signal will send a value every `interval` seconds. - /// - /// To measure from when `self` last sent a value, see `debounce`. - /// - /// - seealso: `debounce` - /// - /// - note: If multiple values are received before the interval has elapsed, - /// the latest value is the one that will be passed on. - /// - /// - note: If `self` terminates while a value is being throttled, that - /// value will be discarded and the returned producer will terminate - /// immediately. - /// - /// - note: If the device time changed backwards before previous date while - /// a value is being throttled, and if there is a new value sent, - /// the new value will be passed anyway. - /// - /// - parameters: - /// - interval: Number of seconds to wait between sent values. - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A producer that sends values at least `interval` seconds - /// appart on a given scheduler. - public func throttle(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { - return lift { $0.throttle(interval, on: scheduler) } - } - - /// Conditionally throttles values sent on the receiver whenever - /// `shouldThrottle` is true, forwarding values on the given scheduler. - /// - /// - note: While `shouldThrottle` remains false, values are forwarded on the - /// given scheduler. If multiple values are received while - /// `shouldThrottle` is true, the latest value is the one that will - /// be passed on. - /// - /// - note: If the input signal terminates while a value is being throttled, - /// that value will be discarded and the returned signal will - /// terminate immediately. - /// - /// - note: If `shouldThrottle` completes before the receiver, and its last - /// value is `true`, the returned signal will remain in the throttled - /// state, emitting no further values until it terminates. - /// - /// - parameters: - /// - shouldThrottle: A boolean property that controls whether values - /// should be throttled. - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A producer that sends values only while `shouldThrottle` is false. - public func throttle(while shouldThrottle: P, on scheduler: Scheduler) -> SignalProducer - where P.Value == Bool - { - // Using `Property.init(_:)` avoids capturing a strong reference - // to `shouldThrottle`, so that we don't extend its lifetime. - let shouldThrottle = Property(shouldThrottle) - - return lift { $0.throttle(while: shouldThrottle, on: scheduler) } - } - - /// Forward the latest value on `scheduler` after at least `interval` - /// seconds have passed since `self` last sent a value. - /// - /// If `self` always sends values more frequently than `interval` seconds, - /// then the returned signal will never send any values. - /// - /// To measure from when the *returned signal* last sent a value, see - /// `throttle`. - /// - /// - seealso: `throttle` - /// - /// - note: If multiple values are received before the interval has elapsed, - /// the latest value is the one that will be passed on. - /// - /// - note: If `self` terminates while a value is being debounced, - /// that value will be discarded and the returned producer will - /// terminate immediately. - /// - /// - parameters: - /// - interval: A number of seconds to wait before sending a value. - /// - scheduler: A scheduler to send values on. - /// - /// - returns: A producer that sends values that are sent from `self` at - /// least `interval` seconds apart. - public func debounce(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { - return lift { $0.debounce(interval, on: scheduler) } - } - - /// Forward events from `self` until `interval`. Then if producer isn't - /// completed yet, fails with `error` on `scheduler`. - /// - /// - note: If the interval is 0, the timeout will be scheduled immediately. - /// The producer must complete synchronously (or on a faster - /// scheduler) to avoid the timeout. - /// - /// - parameters: - /// - interval: Number of seconds to wait for `self` to complete. - /// - error: Error to send with `failed` event if `self` is not completed - /// when `interval` passes. - /// - scheduler: A scheduler to deliver error on. - /// - /// - returns: A producer that sends events for at most `interval` seconds, - /// then, if not `completed` - sends `error` with `failed` event - /// on `scheduler`. - public func timeout(after interval: TimeInterval, raising error: Error, on scheduler: DateScheduler) -> SignalProducer { - return lift { $0.timeout(after: interval, raising: error, on: scheduler) } - } -} - -extension SignalProducerProtocol where Value: OptionalProtocol { - /// Unwraps non-`nil` values and forwards them on the returned signal, `nil` - /// values are dropped. - /// - /// - returns: A producer that sends only non-nil values. - public func skipNil() -> SignalProducer { - return lift { $0.skipNil() } - } -} - -extension SignalProducerProtocol where Value: EventProtocol, Error == NoError { - /// The inverse of materialize(), this will translate a producer of `Event` - /// _values_ into a producer of those events themselves. - /// - /// - returns: A producer that sends values carried by `self` events. - public func dematerialize() -> SignalProducer { - return lift { $0.dematerialize() } - } -} - -extension SignalProducerProtocol where Error == NoError { - /// Promote a producer that does not generate failures into one that can. - /// - /// - note: This does not actually cause failers to be generated for the - /// given producer, but makes it easier to combine with other - /// producers that may fail; for example, with operators like - /// `combineLatestWith`, `zipWith`, `flatten`, etc. - /// - /// - parameters: - /// - _ An `ErrorType`. - /// - /// - returns: A producer that has an instantiatable `ErrorType`. - public func promoteErrors(_: F.Type) -> SignalProducer { - return lift { $0.promoteErrors(F.self) } - } - - /// Forward events from `self` until `interval`. Then if producer isn't - /// completed yet, fails with `error` on `scheduler`. - /// - /// - note: If the interval is 0, the timeout will be scheduled immediately. - /// The producer must complete synchronously (or on a faster - /// scheduler) to avoid the timeout. - /// - /// - parameters: - /// - interval: Number of seconds to wait for `self` to complete. - /// - error: Error to send with `failed` event if `self` is not completed - /// when `interval` passes. - /// - scheudler: A scheduler to deliver error on. - /// - /// - returns: A producer that sends events for at most `interval` seconds, - /// then, if not `completed` - sends `error` with `failed` event - /// on `scheduler`. - public func timeout( - after interval: TimeInterval, - raising error: NewError, - on scheduler: DateScheduler - ) -> SignalProducer { - return lift { $0.timeout(after: interval, raising: error, on: scheduler) } - } - - /// Wait for completion of `self`, *then* forward all events from - /// `replacement`. - /// - /// - note: All values sent from `self` are ignored. - /// - /// - parameters: - /// - replacement: A producer to start when `self` completes. - /// - /// - returns: A producer that sends events from `self` and then from - /// `replacement` when `self` completes. - public func then(_ replacement: SignalProducer) -> SignalProducer { - return self - .promoteErrors(NewError.self) - .then(replacement) - } - - /// Apply a failable `operation` to values from `self` with successful - /// results forwarded on the returned producer and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value. - /// - /// - returns: A producer that forwards successes as `value` events and thrown - /// errors as `failed` events. - public func attempt(_ operation: @escaping (Value) throws -> Void) -> SignalProducer { - return lift { $0.attempt(operation) } - } - - /// Apply a failable `operation` to values from `self` with successful - /// results mapped on the returned producer and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value and attempts to - /// transform it. - /// - /// - returns: A producer that sends successfully mapped values from `self`, - /// or thrown errors as `failed` events. - public func attemptMap(_ operation: @escaping (Value) throws -> U) -> SignalProducer { - return lift { $0.attemptMap(operation) } - } -} - -extension SignalProducer { - /// Create a `SignalProducer` that will attempt the given operation once for - /// each invocation of `start()`. - /// - /// Upon success, the started signal will send the resulting value then - /// complete. Upon failure, the started signal will fail with the error that - /// occurred. - /// - /// - parameters: - /// - operation: A closure that returns instance of `Result`. - /// - /// - returns: A `SignalProducer` that will forward `success`ful `result` as - /// `value` event and then complete or `failed` event if `result` - /// is a `failure`. - public static func attempt(_ operation: @escaping () -> Result) -> SignalProducer { - return self.init { observer, disposable in - operation().analysis(ifSuccess: { value in - observer.send(value: value) - observer.sendCompleted() - }, ifFailure: { error in - observer.send(error: error) - }) - } - } -} - -extension SignalProducerProtocol where Error == AnyError { - /// Create a `SignalProducer` that will attempt the given failable operation once for - /// each invocation of `start()`. - /// - /// Upon success, the started producer will send the resulting value then - /// complete. Upon failure, the started signal will fail with the error that - /// occurred. - /// - /// - parameters: - /// - operation: A failable closure. - /// - /// - returns: A `SignalProducer` that will forward a success as a `value` - /// event and then complete or `failed` event if the closure throws. - public static func attempt(_ operation: @escaping () throws -> Value) -> SignalProducer { - return .attempt { - ReactiveSwift.materialize { - try operation() - } - } - } - - /// Apply a failable `operation` to values from `self` with successful - /// results forwarded on the returned producer and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value. - /// - /// - returns: A producer that forwards successes as `value` events and thrown - /// errors as `failed` events. - public func attempt(_ operation: @escaping (Value) throws -> Void) -> SignalProducer { - return lift { $0.attempt(operation) } - } - - /// Apply a failable `operation` to values from `self` with successful - /// results mapped on the returned producer and thrown errors sent as - /// failed events. - /// - /// - parameters: - /// - operation: A failable closure that accepts a value and attempts to - /// transform it. - /// - /// - returns: A producer that sends successfully mapped values from `self`, - /// or thrown errors as `failed` events. - public func attemptMap(_ operation: @escaping (Value) throws -> U) -> SignalProducer { - return lift { $0.attemptMap(operation) } - } -} - -extension SignalProducerProtocol where Value: Equatable { - /// Forward only those values from `self` which are not duplicates of the - /// immedately preceding value. - /// - /// - note: The first value is always forwarded. - /// - /// - returns: A producer that does not send two equal values sequentially. - public func skipRepeats() -> SignalProducer { - return lift { $0.skipRepeats() } - } -} - -extension SignalProducerProtocol { - /// Forward only those values from `self` that have unique identities across - /// the set of all values that have been seen. - /// - /// - note: This causes the identities to be retained to check for - /// uniqueness. - /// - /// - parameters: - /// - transform: A closure that accepts a value and returns identity - /// value. - /// - /// - returns: A producer that sends unique values during its lifetime. - public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> SignalProducer { - return lift { $0.uniqueValues(transform) } - } -} - -extension SignalProducerProtocol where Value: Hashable { - /// Forward only those values from `self` that are unique across the set of - /// all values that have been seen. - /// - /// - note: This causes the values to be retained to check for uniqueness. - /// Providing a function that returns a unique value for each sent - /// value can help you reduce the memory footprint. - /// - /// - returns: A producer that sends unique values during its lifetime. - public func uniqueValues() -> SignalProducer { - return lift { $0.uniqueValues() } - } -} - -extension SignalProducerProtocol { - /// Injects side effects to be performed upon the specified producer events. - /// - /// - note: In a composed producer, `starting` is invoked in the reverse - /// direction of the flow of events. - /// - /// - parameters: - /// - starting: A closure that is invoked before the producer is started. - /// - started: A closure that is invoked after the producer is started. - /// - event: A closure that accepts an event and is invoked on every - /// received event. - /// - failed: A closure that accepts error object and is invoked for - /// `failed` event. - /// - completed: A closure that is invoked for `completed` event. - /// - interrupted: A closure that is invoked for `interrupted` event. - /// - terminated: A closure that is invoked for any terminating event. - /// - disposed: A closure added as disposable when signal completes. - /// - value: A closure that accepts a value from `value` event. - /// - /// - returns: A producer with attached side-effects for given event cases. - public func on( - starting: (() -> Void)? = nil, - started: (() -> Void)? = nil, - event: ((Event) -> Void)? = nil, - failed: ((Error) -> Void)? = nil, - completed: (() -> Void)? = nil, - interrupted: (() -> Void)? = nil, - terminated: (() -> Void)? = nil, - disposed: (() -> Void)? = nil, - value: ((Value) -> Void)? = nil - ) -> SignalProducer { - return SignalProducer { observer, compositeDisposable in - starting?() - defer { started?() } - - self.startWithSignal { signal, disposable in - compositeDisposable += disposable - signal - .on( - event: event, - failed: failed, - completed: completed, - interrupted: interrupted, - terminated: terminated, - disposed: disposed, - value: value - ) - .observe(observer) - } - } - } - - /// Start the returned producer on the given `Scheduler`. - /// - /// - note: This implies that any side effects embedded in the producer will - /// be performed on the given scheduler as well. - /// - /// - note: Events may still be sent upon other schedulers — this merely - /// affects where the `start()` method is run. - /// - /// - parameters: - /// - scheduler: A scheduler to deliver events on. - /// - /// - returns: A producer that will deliver events on given `scheduler` when - /// started. - public func start(on scheduler: Scheduler) -> SignalProducer { - return SignalProducer { observer, compositeDisposable in - compositeDisposable += scheduler.schedule { - self.startWithSignal { signal, signalDisposable in - compositeDisposable += signalDisposable - signal.observe(observer) - } - } - } - } -} - -extension SignalProducerProtocol { - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer) -> SignalProducer<(Value, B), Error> { - return a.combineLatest(with: b) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer) -> SignalProducer<(Value, B, C), Error> { - return combineLatest(a, b) - .combineLatest(with: c) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer) -> SignalProducer<(Value, B, C, D), Error> { - return combineLatest(a, b, c) - .combineLatest(with: d) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer) -> SignalProducer<(Value, B, C, D, E), Error> { - return combineLatest(a, b, c, d) - .combineLatest(with: e) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F), Error> { - return combineLatest(a, b, c, d, e) - .combineLatest(with: f) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G), Error> { - return combineLatest(a, b, c, d, e, f) - .combineLatest(with: g) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H), Error> { - return combineLatest(a, b, c, d, e, f, g) - .combineLatest(with: h) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H, I), Error> { - return combineLatest(a, b, c, d, e, f, g, h) - .combineLatest(with: i) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. - public static func combineLatest(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ j: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H, I, J), Error> { - return combineLatest(a, b, c, d, e, f, g, h, i) - .combineLatest(with: j) - .map(repack) - } - - /// Combines the values of all the given producers, in the manner described by - /// `combineLatest(with:)`. Will return an empty `SignalProducer` if the sequence is empty. - public static func combineLatest(_ producers: S) -> SignalProducer<[Value], Error> - where S.Iterator.Element == SignalProducer - { - var generator = producers.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { producer, next in - producer.combineLatest(with: next).map { $0.0 + [$0.1] } - } - } - - return .empty - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer) -> SignalProducer<(Value, B), Error> { - return a.zip(with: b) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer) -> SignalProducer<(Value, B, C), Error> { - return zip(a, b) - .zip(with: c) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer) -> SignalProducer<(Value, B, C, D), Error> { - return zip(a, b, c) - .zip(with: d) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer) -> SignalProducer<(Value, B, C, D, E), Error> { - return zip(a, b, c, d) - .zip(with: e) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F), Error> { - return zip(a, b, c, d, e) - .zip(with: f) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G), Error> { - return zip(a, b, c, d, e, f) - .zip(with: g) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H), Error> { - return zip(a, b, c, d, e, f, g) - .zip(with: h) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H, I), Error> { - return zip(a, b, c, d, e, f, g, h) - .zip(with: i) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. - public static func zip(_ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ j: SignalProducer) -> SignalProducer<(Value, B, C, D, E, F, G, H, I, J), Error> { - return zip(a, b, c, d, e, f, g, h, i) - .zip(with: j) - .map(repack) - } - - /// Zips the values of all the given producers, in the manner described by - /// `zipWith`. Will return an empty `SignalProducer` if the sequence is empty. - public static func zip(_ producers: S) -> SignalProducer<[Value], Error> - where S.Iterator.Element == SignalProducer - { - var generator = producers.makeIterator() - if let first = generator.next() { - let initial = first.map { [$0] } - return IteratorSequence(generator).reduce(initial) { producer, next in - producer.zip(with: next).map { $0.0 + [$0.1] } - } - } - - return .empty - } -} - -extension SignalProducerProtocol { - /// Repeat `self` a total of `count` times. In other words, start producer - /// `count` number of times, each one after previously started producer - /// completes. - /// - /// - note: Repeating `1` time results in an equivalent signal producer. - /// - /// - note: Repeating `0` times results in a producer that instantly - /// completes. - /// - /// - parameters: - /// - count: Number of repetitions. - /// - /// - returns: A signal producer start sequentially starts `self` after - /// previously started producer completes. - public func `repeat`(_ count: Int) -> SignalProducer { - precondition(count >= 0) - - if count == 0 { - return .empty - } else if count == 1 { - return producer - } - - return SignalProducer { observer, disposable in - let serialDisposable = SerialDisposable() - disposable += serialDisposable - - func iterate(_ current: Int) { - self.startWithSignal { signal, signalDisposable in - serialDisposable.inner = signalDisposable - - signal.observe { event in - if case .completed = event { - let remainingTimes = current - 1 - if remainingTimes > 0 { - iterate(remainingTimes) - } else { - observer.sendCompleted() - } - } else { - observer.action(event) - } - } - } - } - - iterate(count) - } - } - - /// Ignore failures up to `count` times. - /// - /// - precondition: `count` must be non-negative integer. - /// - /// - parameters: - /// - count: Number of retries. - /// - /// - returns: A signal producer that restarts up to `count` times. - public func retry(upTo count: Int) -> SignalProducer { - precondition(count >= 0) - - if count == 0 { - return producer - } else { - return flatMapError { _ in - self.retry(upTo: count - 1) - } - } - } - - /// Wait for completion of `self`, *then* forward all events from - /// `replacement`. Any failure or interruption sent from `self` is - /// forwarded immediately, in which case `replacement` will not be started, - /// and none of its events will be be forwarded. - /// - /// - note: All values sent from `self` are ignored. - /// - /// - parameters: - /// - replacement: A producer to start when `self` completes. - /// - /// - returns: A producer that sends events from `self` and then from - /// `replacement` when `self` completes. - public func then(_ replacement: SignalProducer) -> SignalProducer { - return SignalProducer { observer, observerDisposable in - self.startWithSignal { signal, signalDisposable in - observerDisposable += signalDisposable - - signal.observe { event in - switch event { - case let .failed(error): - observer.send(error: error) - case .completed: - observerDisposable += replacement.start(observer) - case .interrupted: - observer.sendInterrupted() - case .value: - break - } - } - } - } - } - - /// Wait for completion of `self`, *then* forward all events from - /// `replacement`. Any failure or interruption sent from `self` is - /// forwarded immediately, in which case `replacement` will not be started, - /// and none of its events will be be forwarded. - /// - /// - note: All values sent from `self` are ignored. - /// - /// - parameters: - /// - replacement: A producer to start when `self` completes. - /// - /// - returns: A producer that sends events from `self` and then from - /// `replacement` when `self` completes. - public func then(_ replacement: SignalProducer) -> SignalProducer { - return self.then(replacement.promoteErrors(Error.self)) - } - - /// Start the producer, then block, waiting for the first value. - /// - /// When a single value or error is sent, the returned `Result` will - /// represent those cases. However, when no values are sent, `nil` will be - /// returned. - /// - /// - returns: Result when single `value` or `failed` event is received. - /// `nil` when no events are received. - public func first() -> Result? { - return take(first: 1).single() - } - - /// Start the producer, then block, waiting for events: `value` and - /// `completed`. - /// - /// When a single value or error is sent, the returned `Result` will - /// represent those cases. However, when no values are sent, or when more - /// than one value is sent, `nil` will be returned. - /// - /// - returns: Result when single `value` or `failed` event is received. - /// `nil` when 0 or more than 1 events are received. - public func single() -> Result? { - let semaphore = DispatchSemaphore(value: 0) - var result: Result? - - take(first: 2).start { event in - switch event { - case let .value(value): - if result != nil { - // Move into failure state after recieving another value. - result = nil - return - } - result = .success(value) - case let .failed(error): - result = .failure(error) - semaphore.signal() - case .completed, .interrupted: - semaphore.signal() - } - } - - semaphore.wait() - return result - } - - /// Start the producer, then block, waiting for the last value. - /// - /// When a single value or error is sent, the returned `Result` will - /// represent those cases. However, when no values are sent, `nil` will be - /// returned. - /// - /// - returns: Result when single `value` or `failed` event is received. - /// `nil` when no events are received. - public func last() -> Result? { - return take(last: 1).single() - } - - /// Starts the producer, then blocks, waiting for completion. - /// - /// When a completion or error is sent, the returned `Result` will represent - /// those cases. - /// - /// - returns: Result when single `completion` or `failed` event is - /// received. - public func wait() -> Result<(), Error> { - return then(SignalProducer<(), Error>(value: ())).last() ?? .success(()) - } - - /// Creates a new `SignalProducer` that will multicast values emitted by - /// the underlying producer, up to `capacity`. - /// This means that all clients of this `SignalProducer` will see the same - /// version of the emitted values/errors. - /// - /// The underlying `SignalProducer` will not be started until `self` is - /// started for the first time. When subscribing to this producer, all - /// previous values (up to `capacity`) will be emitted, followed by any new - /// values. - /// - /// If you find yourself needing *the current value* (the last buffered - /// value) you should consider using `PropertyType` instead, which, unlike - /// this operator, will guarantee at compile time that there's always a - /// buffered value. This operator is not recommended in most cases, as it - /// will introduce an implicit relationship between the original client and - /// the rest, so consider alternatives like `PropertyType`, or representing - /// your stream using a `Signal` instead. - /// - /// This operator is only recommended when you absolutely need to introduce - /// a layer of caching in front of another `SignalProducer`. - /// - /// - precondition: `capacity` must be non-negative integer. - /// - /// - parameters: - /// - capacity: Number of values to hold. - /// - /// - returns: A caching producer that will hold up to last `capacity` - /// values. - public func replayLazily(upTo capacity: Int) -> SignalProducer { - precondition(capacity >= 0, "Invalid capacity: \(capacity)") - - // This will go "out of scope" when the returned `SignalProducer` goes - // out of scope. This lets us know when we're supposed to dispose the - // underlying producer. This is necessary because `struct`s don't have - // `deinit`. - let lifetimeToken = Lifetime.Token() - let lifetime = Lifetime(lifetimeToken) - - let state = Atomic(ReplayState(upTo: capacity)) - - let start: Atomic<(() -> Void)?> = Atomic { - // Start the underlying producer. - self - .take(during: lifetime) - .start { event in - let observers: Bag.Observer>? = state.modify { state in - defer { state.enqueue(event) } - return state.observers - } - observers?.forEach { $0.action(event) } - } - } - - return SignalProducer { observer, disposable in - // Don't dispose of the original producer until all observers - // have terminated. - disposable += { _ = lifetimeToken } - - while true { - var result: Result>! - state.modify { - result = $0.observe(observer) - } - - switch result! { - case let .success(token): - if let token = token { - disposable += { - state.modify { - $0.removeObserver(using: token) - } - } - } - - // Start the underlying producer if it has never been started. - start.swap(nil)?() - - // Terminate the replay loop. - return - - case let .failure(error): - error.values.forEach(observer.send(value:)) - } - } - } - } -} - -extension SignalProducerProtocol where Value == Bool { - /// Create a producer that computes a logical NOT in the latest values of `self`. - /// - /// - returns: A producer that emits the logical NOT results. - public var negated: SignalProducer { - return self.lift { $0.negated } - } - - /// Create a producer that computes a logical AND between the latest values of `self` - /// and `producer`. - /// - /// - parameters: - /// - producer: Producer to be combined with `self`. - /// - /// - returns: A producer that emits the logical AND results. - public func and(_ producer: SignalProducer) -> SignalProducer { - return self.liftLeft(Signal.and)(producer) - } - - /// Create a producer that computes a logical AND between the latest values of `self` - /// and `signal`. - /// - /// - parameters: - /// - signal: Signal to be combined with `self`. - /// - /// - returns: A producer that emits the logical AND results. - public func and(_ signal: Signal) -> SignalProducer { - return self.lift(Signal.and)(signal) - } - - /// Create a producer that computes a logical OR between the latest values of `self` - /// and `producer`. - /// - /// - parameters: - /// - producer: Producer to be combined with `self`. - /// - /// - returns: A producer that emits the logical OR results. - public func or(_ producer: SignalProducer) -> SignalProducer { - return self.liftLeft(Signal.or)(producer) - } - - /// Create a producer that computes a logical OR between the latest values of `self` - /// and `signal`. - /// - /// - parameters: - /// - signal: Signal to be combined with `self`. - /// - /// - returns: A producer that emits the logical OR results. - public func or(_ signal: Signal) -> SignalProducer { - return self.lift(Signal.or)(signal) - } -} - -/// Represents a recoverable error of an observer not being ready for an -/// attachment to a `ReplayState`, and the observer should replay the supplied -/// values before attempting to observe again. -private struct ReplayError: Error { - /// The values that should be replayed by the observer. - let values: [Value] -} - -private struct ReplayState { - let capacity: Int - - /// All cached values. - var values: [Value] = [] - - /// A termination event emitted by the underlying producer. - /// - /// This will be nil if termination has not occurred. - var terminationEvent: Event? - - /// The observers currently attached to the caching producer, or `nil` if the - /// caching producer was terminated. - var observers: Bag.Observer>? = Bag() - - /// The set of in-flight replay buffers. - var replayBuffers: [ObjectIdentifier: [Value]] = [:] - - /// Initialize the replay state. - /// - /// - parameters: - /// - capacity: The maximum amount of values which can be cached by the - /// replay state. - init(upTo capacity: Int) { - self.capacity = capacity - } - - /// Attempt to observe the replay state. - /// - /// - warning: Repeatedly observing the replay state with the same observer - /// should be avoided. - /// - /// - parameters: - /// - observer: The observer to be registered. - /// - /// - returns: - /// If the observer is successfully attached, a `Result.success` with the - /// corresponding removal token would be returned. Otherwise, a - /// `Result.failure` with a `ReplayError` would be returned. - mutating func observe(_ observer: Signal.Observer) -> Result> { - // Since the only use case is `replayLazily`, which always creates a unique - // `Observer` for every produced signal, we can use the ObjectIdentifier of - // the `Observer` to track them directly. - let id = ObjectIdentifier(observer) - - switch replayBuffers[id] { - case .none where !values.isEmpty: - // No in-flight replay buffers was found, but the `ReplayState` has one or - // more cached values in the `ReplayState`. The observer should replay - // them before attempting to observe again. - replayBuffers[id] = [] - return .failure(ReplayError(values: values)) - - case let .some(buffer) where !buffer.isEmpty: - // An in-flight replay buffer was found with one or more buffered values. - // The observer should replay them before attempting to observe again. - defer { replayBuffers[id] = [] } - return .failure(ReplayError(values: buffer)) - - case let .some(buffer) where buffer.isEmpty: - // Since an in-flight but empty replay buffer was found, the observer is - // ready to be attached to the `ReplayState`. - replayBuffers.removeValue(forKey: id) - - default: - // No values has to be replayed. The observer is ready to be attached to - // the `ReplayState`. - break - } - - if let event = terminationEvent { - observer.action(event) - } - - return .success(observers?.insert(observer)) - } - - /// Enqueue the supplied event to the replay state. - /// - /// - parameter: - /// - event: The event to be cached. - mutating func enqueue(_ event: Event) { - switch event { - case let .value(value): - for key in replayBuffers.keys { - replayBuffers[key]!.append(value) - } - - switch capacity { - case 0: - // With a capacity of zero, `state.values` can never be filled. - break - - case 1: - values = [value] - - default: - values.append(value) - - let overflow = values.count - capacity - if overflow > 0 { - values.removeFirst(overflow) - } - } - - case .completed, .failed, .interrupted: - // Disconnect all observers and prevent future attachments. - terminationEvent = event - observers = nil - } - } - - /// Remove the observer represented by the supplied token. - /// - /// - parameters: - /// - token: The token of the observer to be removed. - mutating func removeObserver(using token: RemovalToken) { - observers?.remove(using: token) - } -} - -/// Create a repeating timer of the given interval, with a reasonable default -/// leeway, sending updates on the given scheduler. -/// -/// - note: This timer will never complete naturally, so all invocations of -/// `start()` must be disposed to avoid leaks. -/// -/// - precondition: Interval must be non-negative number. -/// -/// - note: If you plan to specify an `interval` value greater than 200,000 -/// seconds, use `timer(interval:on:leeway:)` instead -/// and specify your own `leeway` value to avoid potential overflow. -/// -/// - parameters: -/// - interval: An interval between invocations. -/// - scheduler: A scheduler to deliver events on. -/// -/// - returns: A producer that sends `NSDate` values every `interval` seconds. -public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler) -> SignalProducer { - // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of - // at least 10% of the timer interval. - return timer(interval: interval, on: scheduler, leeway: interval * 0.1) -} - -/// Creates a repeating timer of the given interval, sending updates on the -/// given scheduler. -/// -/// - note: This timer will never complete naturally, so all invocations of -/// `start()` must be disposed to avoid leaks. -/// -/// - precondition: Interval must be non-negative number. -/// -/// - precondition: Leeway must be non-negative number. -/// -/// - parameters: -/// - interval: An interval between invocations. -/// - scheduler: A scheduler to deliver events on. -/// - leeway: Interval leeway. Apple's "Power Efficiency Guide for Mac Apps" -/// recommends a leeway of at least 10% of the timer interval. -/// -/// - returns: A producer that sends `NSDate` values every `interval` seconds. -public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler, leeway: DispatchTimeInterval) -> SignalProducer { - precondition(interval.timeInterval >= 0) - precondition(leeway.timeInterval >= 0) - - return SignalProducer { observer, compositeDisposable in - compositeDisposable += scheduler.schedule(after: scheduler.currentDate.addingTimeInterval(interval), - interval: interval, - leeway: leeway, - action: { observer.send(value: scheduler.currentDate) }) - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/TupleExtensions.swift b/Example/Pods/ReactiveSwift/Sources/TupleExtensions.swift deleted file mode 100644 index f976369..0000000 --- a/Example/Pods/ReactiveSwift/Sources/TupleExtensions.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// TupleExtensions.swift -// ReactiveSwift -// -// Created by Justin Spahr-Summers on 2014-12-20. -// Copyright (c) 2014 GitHub. All rights reserved. -// - -/// Adds a value into an N-tuple, returning an (N+1)-tuple. -/// -/// Supports creating tuples up to 10 elements long. -internal func repack(_ t: (A, B), value: C) -> (A, B, C) { - return (t.0, t.1, value) -} - -internal func repack(_ t: (A, B, C), value: D) -> (A, B, C, D) { - return (t.0, t.1, t.2, value) -} - -internal func repack(_ t: (A, B, C, D), value: E) -> (A, B, C, D, E) { - return (t.0, t.1, t.2, t.3, value) -} - -internal func repack(_ t: (A, B, C, D, E), value: F) -> (A, B, C, D, E, F) { - return (t.0, t.1, t.2, t.3, t.4, value) -} - -internal func repack(_ t: (A, B, C, D, E, F), value: G) -> (A, B, C, D, E, F, G) { - return (t.0, t.1, t.2, t.3, t.4, t.5, value) -} - -internal func repack(_ t: (A, B, C, D, E, F, G), value: H) -> (A, B, C, D, E, F, G, H) { - return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, value) -} - -internal func repack(_ t: (A, B, C, D, E, F, G, H), value: I) -> (A, B, C, D, E, F, G, H, I) { - return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, value) -} - -internal func repack(_ t: (A, B, C, D, E, F, G, H, I), value: J) -> (A, B, C, D, E, F, G, H, I, J) { - return (t.0, t.1, t.2, t.3, t.4, t.5, t.6, t.7, t.8, value) -} diff --git a/Example/Pods/ReactiveSwift/Sources/UnidirectionalBinding.swift b/Example/Pods/ReactiveSwift/Sources/UnidirectionalBinding.swift deleted file mode 100644 index 825fad1..0000000 --- a/Example/Pods/ReactiveSwift/Sources/UnidirectionalBinding.swift +++ /dev/null @@ -1,166 +0,0 @@ -import Foundation -import Dispatch -import enum Result.NoError - -precedencegroup BindingPrecedence { - associativity: right - - // Binds tighter than assignment but looser than everything else - higherThan: AssignmentPrecedence -} - -infix operator <~ : BindingPrecedence - -/// Describes a source which can be bound. -public protocol BindingSource { - associatedtype Value - associatedtype Error: Swift.Error - - /// Observe the binding source by sending any events to the given observer. - @discardableResult - func observe(_ observer: Observer, during lifetime: Lifetime) -> Disposable? -} - -extension Signal: BindingSource { - @discardableResult - public func observe(_ observer: Observer, during lifetime: Lifetime) -> Disposable? { - return self.take(during: lifetime).observe(observer) - } -} - -extension SignalProducer: BindingSource { - @discardableResult - public func observe(_ observer: ProducedSignal.Observer, during lifetime: Lifetime) -> Disposable? { - var disposable: Disposable! - - self - .take(during: lifetime) - .startWithSignal { signal, signalDisposable in - disposable = signalDisposable - signal.observe(observer) - } - - return disposable - } -} - -/// Describes an entity which be bond towards. -public protocol BindingTargetProvider { - associatedtype Value - - var bindingTarget: BindingTarget { get } -} - -/// Binds a source to a target, updating the target's value to the latest -/// value sent by the source. -/// -/// - note: The binding will automatically terminate when the target is -/// deinitialized, or when the source sends a `completed` event. -/// -/// ```` -/// let property = MutableProperty(0) -/// let signal = Signal({ /* do some work after some time */ }) -/// property <~ signal -/// ```` -/// -/// ```` -/// let property = MutableProperty(0) -/// let signal = Signal({ /* do some work after some time */ }) -/// let disposable = property <~ signal -/// ... -/// // Terminates binding before property dealloc or signal's -/// // `completed` event. -/// disposable.dispose() -/// ```` -/// -/// - parameters: -/// - target: A target to be bond to. -/// - source: A source to bind. -/// -/// - returns: A disposable that can be used to terminate binding before the -/// deinitialization of the target or the source's `completed` -/// event. -@discardableResult -public func <~ - - (provider: Provider, source: Source) -> Disposable? - where Source.Value == Provider.Value, Source.Error == NoError -{ - return source.observe(Observer(value: provider.bindingTarget.action), - during: provider.bindingTarget.lifetime) -} - -/// Binds a source to a target, updating the target's value to the latest -/// value sent by the source. -/// -/// - note: The binding will automatically terminate when the target is -/// deinitialized, or when the source sends a `completed` event. -/// -/// ```` -/// let property = MutableProperty(0) -/// let signal = Signal({ /* do some work after some time */ }) -/// property <~ signal -/// ```` -/// -/// ```` -/// let property = MutableProperty(0) -/// let signal = Signal({ /* do some work after some time */ }) -/// let disposable = property <~ signal -/// ... -/// // Terminates binding before property dealloc or signal's -/// // `completed` event. -/// disposable.dispose() -/// ```` -/// -/// - parameters: -/// - target: A target to be bond to. -/// - source: A source to bind. -/// -/// - returns: A disposable that can be used to terminate binding before the -/// deinitialization of the target or the source's `completed` -/// event. -@discardableResult -public func <~ - - (provider: Provider, source: Source) -> Disposable? - where Provider.Value: OptionalProtocol, Source.Value == Provider.Value.Wrapped, Source.Error == NoError -{ - let action = provider.bindingTarget.action - return source.observe(Observer(value: { action(Provider.Value(reconstructing: $0)) }), - during: provider.bindingTarget.lifetime) -} - -/// A binding target that can be used with the `<~` operator. -public struct BindingTarget: BindingTargetProvider { - public let lifetime: Lifetime - public let action: (Value) -> Void - - public var bindingTarget: BindingTarget { - return self - } - - /// Creates a binding target. - /// - /// - parameters: - /// - lifetime: The expected lifetime of any bindings towards `self`. - /// - action: The action to consume values. - public init(lifetime: Lifetime, action: @escaping (Value) -> Void) { - self.action = action - self.lifetime = lifetime - } - - /// Creates a binding target which consumes values on the specified scheduler. - /// - /// - parameters: - /// - scheduler: The scheduler on which the `setter` consumes the values. - /// - lifetime: The expected lifetime of any bindings towards `self`. - /// - action: The action to consume values. - public init(on scheduler: Scheduler, lifetime: Lifetime, action: @escaping (Value) -> Void) { - let setter: (Value) -> Void = { value in - scheduler.schedule { - action(value) - } - } - self.init(lifetime: lifetime, action: setter) - } -} diff --git a/Example/Pods/ReactiveSwift/Sources/ValidatingProperty.swift b/Example/Pods/ReactiveSwift/Sources/ValidatingProperty.swift deleted file mode 100644 index dd6d558..0000000 --- a/Example/Pods/ReactiveSwift/Sources/ValidatingProperty.swift +++ /dev/null @@ -1,327 +0,0 @@ -import Result - -/// A mutable property that validates mutations before committing them. -/// -/// If the property wraps an arbitrary mutable property, changes originated from -/// the inner property are monitored, and would be automatically validated. -/// Note that these would still appear as committed values even if they fail the -/// validation. -/// -/// ``` -/// let root = MutableProperty("Valid") -/// let outer = MutableValidatingProperty(root) { -/// $0 == "Valid" ? .valid : .invalid(.outerInvalid) -/// } -/// -/// outer.result.value // `.valid("Valid") -/// -/// root.value = "🎃" -/// outer.result.value // `.invalid("🎃", .outerInvalid)` -/// ``` -public final class ValidatingProperty: MutablePropertyProtocol { - private let getter: () -> Value - private let setter: (Value) -> Void - - /// The result of the last attempted edit of the root property. - public let result: Property> - - /// The current value of the property. - /// - /// The value could have failed the validation. Refer to `result` for the - /// latest validation result. - public var value: Value { - get { return getter() } - set { setter(newValue) } - } - - /// A producer for Signals that will send the property's current value, - /// followed by all changes over time, then complete when the property has - /// deinitialized. - public let producer: SignalProducer - - /// A signal that will send the property's changes over time, - /// then complete when the property has deinitialized. - public let signal: Signal - - /// The lifetime of the property. - public let lifetime: Lifetime - - /// Create a `ValidatingProperty` that presents a mutable validating - /// view for an inner mutable property. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - note: `inner` is retained by the created property. - /// - /// - parameters: - /// - inner: The inner property which validated values are committed to. - /// - validator: The closure to invoke for any proposed value to `self`. - public init( - _ inner: Inner, - _ validator: @escaping (Value) -> ValidatorOutput - ) where Inner.Value == Value { - getter = { inner.value } - producer = inner.producer - signal = inner.signal - lifetime = inner.lifetime - - // This flag temporarily suspends the monitoring on the inner property for - // writebacks that are triggered by successful validations. - var isSettingInnerValue = false - - (result, setter) = inner.withValue { initial in - let mutableResult = MutableProperty(ValidationResult(initial, validator(initial))) - - mutableResult <~ inner.signal - .filter { _ in !isSettingInnerValue } - .map { ValidationResult($0, validator($0)) } - - return (Property(capturing: mutableResult), { input in - // Acquire the lock of `inner` to ensure no modification happens until - // the validation logic here completes. - inner.withValue { _ in - let writebackValue: Value? = mutableResult.modify { result in - result = ValidationResult(input, validator(input)) - return result.value - } - - if let value = writebackValue { - isSettingInnerValue = true - inner.value = value - isSettingInnerValue = false - } - } - }) - } - } - - /// Create a `ValidatingProperty` that validates mutations before - /// committing them. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - parameters: - /// - initial: The initial value of the property. It is not required to - /// pass the validation as specified by `validator`. - /// - validator: The closure to invoke for any proposed value to `self`. - public convenience init( - _ initial: Value, - _ validator: @escaping (Value) -> ValidatorOutput - ) { - self.init(MutableProperty(initial), validator) - } - - /// Create a `ValidatingProperty` that presents a mutable validating - /// view for an inner mutable property. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - note: `inner` is retained by the created property. - /// - /// - parameters: - /// - inner: The inner property which validated values are committed to. - /// - other: The property that `validator` depends on. - /// - validator: The closure to invoke for any proposed value to `self`. - public convenience init( - _ inner: MutableProperty, - with other: Other, - _ validator: @escaping (Value, Other.Value) -> ValidatorOutput - ) { - // Capture a copy that reflects `other` without influencing the lifetime of - // `other`. - let other = Property(other) - - self.init(inner) { input in - return validator(input, other.value) - } - - // When `other` pushes out a new value, the resulting property would react - // by revalidating itself with its last attempted value, regardless of - // success or failure. - other.signal - .take(during: lifetime) - .observeValues { [weak self] _ in - guard let s = self else { return } - - switch s.result.value { - case let .invalid(value, _): - s.value = value - - case let .coerced(_, value, _): - s.value = value - - case let .valid(value): - s.value = value - } - } - } - - /// Create a `ValidatingProperty` that validates mutations before - /// committing them. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - parameters: - /// - initial: The initial value of the property. It is not required to - /// pass the validation as specified by `validator`. - /// - other: The property that `validator` depends on. - /// - validator: The closure to invoke for any proposed value to `self`. - public convenience init( - _ initial: Value, - with other: Other, - _ validator: @escaping (Value, Other.Value) -> ValidatorOutput - ) { - self.init(MutableProperty(initial), with: other, validator) - } - - /// Create a `ValidatingProperty` that presents a mutable validating - /// view for an inner mutable property. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - note: `inner` is retained by the created property. - /// - /// - parameters: - /// - inner: The inner property which validated values are committed to. - /// - other: The property that `validator` depends on. - /// - validator: The closure to invoke for any proposed value to `self`. - public convenience init( - _ inner: MutableProperty, - with other: ValidatingProperty, - _ validator: @escaping (Value, U) -> ValidatorOutput - ) { - self.init(inner, with: other, validator) - } - - /// Create a `ValidatingProperty` that validates mutations before - /// committing them. - /// - /// The proposed value is only committed when `valid` is returned by the - /// `validator` closure. - /// - /// - parameters: - /// - initial: The initial value of the property. It is not required to - /// pass the validation as specified by `validator`. - /// - other: The property that `validator` depends on. - /// - validator: The closure to invoke for any proposed value to `self`. - public convenience init( - _ initial: Value, - with other: ValidatingProperty, - _ validator: @escaping (Value, U) -> ValidatorOutput - ) { - // Capture only `other.result` but not `other`. - let otherValidations = other.result - - self.init(initial) { input in - let otherValue: U - - switch otherValidations.value { - case let .valid(value): - otherValue = value - - case let .coerced(_, value, _): - otherValue = value - - case let .invalid(value, _): - otherValue = value - } - - return validator(input, otherValue) - } - - // When `other` pushes out a new validation result, the resulting property - // would react by revalidating itself with its last attempted value, - // regardless of success or failure. - otherValidations.signal - .take(during: lifetime) - .observeValues { [weak self] _ in - guard let s = self else { return } - - switch s.result.value { - case let .invalid(value, _): - s.value = value - - case let .coerced(_, value, _): - s.value = value - - case let .valid(value): - s.value = value - } - } - } -} - -/// Represents a decision of a validator of a validating property made on a -/// proposed value. -public enum ValidatorOutput { - /// The proposed value is valid. - case valid - - /// The proposed value is invalid, but the validator coerces it into a - /// replacement which it deems valid. - case coerced(Value, Error?) - - /// The proposed value is invalid. - case invalid(Error) -} - -/// Represents the result of the validation performed by a validating property. -public enum ValidationResult { - /// The proposed value is valid. - case valid(Value) - - /// The proposed value is invalid, but the validator was able to coerce it - /// into a replacement which it deemed valid. - case coerced(replacement: Value, proposed: Value, error: Error?) - - /// The proposed value is invalid. - case invalid(Value, Error) - - /// Whether the value is invalid. - public var isInvalid: Bool { - if case .invalid = self { - return true - } else { - return false - } - } - - /// Extract the valid value, or `nil` if the value is invalid. - public var value: Value? { - switch self { - case let .valid(value): - return value - case let .coerced(value, _, _): - return value - case .invalid: - return nil - } - } - - /// Extract the error if the value is invalid. - public var error: Error? { - if case let .invalid(_, error) = self { - return error - } else { - return nil - } - } - - fileprivate init(_ value: Value, _ output: ValidatorOutput) { - switch output { - case .valid: - self = .valid(value) - - case let .coerced(replacement, error): - self = .coerced(replacement: replacement, proposed: value, error: error) - - case let .invalid(error): - self = .invalid(value, error) - } - } -} diff --git a/Example/Pods/Realm/LICENSE b/Example/Pods/Realm/LICENSE deleted file mode 100644 index 8a84f2b..0000000 --- a/Example/Pods/Realm/LICENSE +++ /dev/null @@ -1,244 +0,0 @@ -TABLE OF CONTENTS - -1. Apache License version 2.0 -2. Realm Components -3. Export Compliance - -------------------------------------------------------------------------------- - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -REALM COMPONENTS - -This software contains components with separate copyright and license terms. -Your use of these components is subject to the terms and conditions of the -following licenses. - -For the Realm Core component - - Realm Core Binary License - - Copyright (c) 2011-2016 Realm Inc All rights reserved - - Redistribution and use in binary form, with or without modification, is - permitted provided that the following conditions are met: - - 1. You agree not to attempt to decompile, disassemble, reverse engineer or - otherwise discover the source code from which the binary code was derived. - You may, however, access and obtain a separate license for most of the - source code from which this Software was created, at - http://realm.io/pricing/. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -EXPORT COMPLIANCE - -You understand that the Software may contain cryptographic functions that may be -subject to export restrictions, and you represent and warrant that you are not -(i) located in a jurisdiction that is subject to United States economic -sanctions (“Prohibited Jurisdiction”), including Cuba, Iran, North Korea, -Sudan, Syria or the Crimea region, (ii) a person listed on any U.S. government -blacklist (to include the List of Specially Designated Nationals and Blocked -Persons or the Consolidated Sanctions List administered by the U.S. Department -of the Treasury’s Office of Foreign Assets Control, or the Denied Persons List -or Entity List administered by the U.S. Department of Commerce) -(“Sanctioned Person”), or (iii) controlled or 50% or more owned by a Sanctioned -Person. - -You agree to comply with all export, re-export and import restrictions and -regulations of the U.S. Department of Commerce or other agency or authority of -the United States or other applicable countries. You also agree not to transfer, -or authorize the transfer of, directly or indirectly, of the Software to any -Prohibited Jurisdiction, or otherwise in violation of any such restrictions or -regulations. diff --git a/Example/Pods/Realm/README.md b/Example/Pods/Realm/README.md deleted file mode 100644 index b31ae47..0000000 --- a/Example/Pods/Realm/README.md +++ /dev/null @@ -1,74 +0,0 @@ -![Realm](https://github.com/realm/realm-cocoa/raw/master/logo.png) - -Realm is a mobile database that runs directly inside phones, tablets or wearables. -This repository holds the source code for the iOS, macOS, tvOS & watchOS versions of Realm Swift & Realm Objective-C. - -## Features - -* **Mobile-first:** Realm is the first database built from the ground up to run directly inside phones, tablets and wearables. -* **Simple:** Data is directly [exposed as objects](https://realm.io/docs/objc/latest/#models) and [queryable by code](https://realm.io/docs/objc/latest/#queries), removing the need for ORM's riddled with performance & maintenance issues. Most of our users pick it up intuitively, getting simple apps up & running in minutes. -* **Modern:** Realm supports relationships, generics, vectorization and even Swift. -* **Fast:** Realm is faster than even raw SQLite on common operations, while maintaining an extremely rich feature set. - -## Getting Started - -Please see the detailed instructions in our docs to add [Realm Objective-C](https://realm.io/docs/objc/latest/#installation) _or_ [Realm Swift](https://realm.io/docs/swift/latest/#installation) to your Xcode project. - -## Documentation - -### Realm Objective-C - -The documentation can be found at [realm.io/docs/objc/latest](https://realm.io/docs/objc/latest). -The API reference is located at [realm.io/docs/objc/latest/api](https://realm.io/docs/objc/latest/api). - -### Realm Swift - -The documentation can be found at [realm.io/docs/swift/latest](https://realm.io/docs/swift/latest). -The API reference is located at [realm.io/docs/swift/latest/api](https://realm.io/docs/swift/latest/api). - -## Getting Help - -- **Need help with your code?**: Look for previous questions on the [#realm tag](https://stackoverflow.com/questions/tagged/realm?sort=newest) — or [ask a new question](https://stackoverflow.com/questions/ask?tags=realm). We actively monitor & answer questions on SO! -- **Have a bug to report?** [Open an issue](https://github.com/realm/realm-cocoa/issues/new). If possible, include the version of Realm, a full log, the Realm file, and a project that shows the issue. -- **Have a feature request?** [Open an issue](https://github.com/realm/realm-cocoa/issues/new). Tell us what the feature should do, and why you want the feature. -- Sign up for our [**Community Newsletter**](https://www2.realm.io/l/210132/2016-12-05/fy9m) to get regular tips, learn about other use-cases and get alerted of blogposts and tutorials about Realm. - -## Building Realm - -In case you don't want to use the precompiled version, you can build Realm yourself from source. - -Prerequisites: - -* Building Realm requires Xcode 7.3.1 or Xcode 8.x. -* If cloning from git, submodules are required: `git submodule update --init --recursive`. -* Building Realm documentation requires [jazzy](https://github.com/realm/jazzy) - -Once you have all the necessary prerequisites, building Realm.framework just takes a single command: `sh build.sh build`. You'll need an internet connection the first time you build Realm to download the core binary. - -Run `sh build.sh help` to see all the actions you can perform (build ios/osx, generate docs, test, etc.). - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) for more details! - -This project adheres to the [Contributor Covenant Code of Conduct](https://realm.io/conduct). -By participating, you are expected to uphold this code. Please report -unacceptable behavior to [info@realm.io](mailto:info@realm.io). - -## License - -Realm Objective-C & Realm Swift are published under the Apache 2.0 license. -Realm Core is also published under the Apache 2.0 license and is available -[here](https://github.com/realm/realm-core). - -**This product is not being made available to any person located in Cuba, Iran, -North Korea, Sudan, Syria or the Crimea region, or to any other person that is -not eligible to receive the product under U.S. law.** - -## Feedback - -**_If you use Realm and are happy with it, all we ask is that you please consider sending out a tweet mentioning [@realm](https://twitter.com/realm) or email [help@realm.io](mailto:help@realm.io) to share your thoughts!_** - -**_And if you don't like it, please let us know what you would like improved, so we can fix it!_** - -![analytics](https://ga-beacon.appspot.com/UA-50247013-2/realm-cocoa/README?pixel) diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp deleted file mode 100644 index 165021d..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "collection_notifications.hpp" - -#include "impl/collection_notifier.hpp" - -using namespace realm; -using namespace realm::_impl; - -NotificationToken::NotificationToken(std::shared_ptr<_impl::CollectionNotifier> notifier, size_t token) -: m_notifier(std::move(notifier)), m_token(token) -{ -} - -NotificationToken::~NotificationToken() -{ - // m_notifier itself (and not just the pointed-to thing) needs to be accessed - // atomically to ensure that there are no data races when the token is - // destroyed after being modified on a different thread. - // This is needed despite the token not being thread-safe in general as - // users find it very surprising for obj-c objects to care about what - // thread they are deallocated on. - if (auto notifier = m_notifier.exchange({})) { - notifier->remove_callback(m_token); - } -} - -NotificationToken::NotificationToken(NotificationToken&&) = default; - -NotificationToken& NotificationToken::operator=(realm::NotificationToken&& rgt) -{ - if (this != &rgt) { - if (auto notifier = m_notifier.exchange({})) { - notifier->remove_callback(m_token); - } - m_notifier = std::move(rgt.m_notifier); - m_token = rgt.m_token; - } - return *this; -} - -void NotificationToken::suppress_next() -{ - m_notifier.load()->suppress_next_notification(m_token); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp deleted file mode 100644 index 60f7a66..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/external_commit_helper.hpp" - -#include "impl/realm_coordinator.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace realm; -using namespace realm::_impl; - -namespace { -// Write a byte to a pipe to notify anyone waiting for data on the pipe -void notify_fd(int fd, int read_fd) -{ - while (true) { - char c = 0; - ssize_t ret = write(fd, &c, 1); - if (ret == 1) { - break; - } - - // If the pipe's buffer is full, we need to read some of the old data in - // it to make space. We don't just read in the code waiting for - // notifications so that we can notify multiple waiters with a single - // write. - assert(ret == -1 && errno == EAGAIN); - char buff[1024]; - read(read_fd, buff, sizeof buff); - } -} -} // anonymous namespace - -void ExternalCommitHelper::FdHolder::close() -{ - if (m_fd != -1) { - ::close(m_fd); - } - m_fd = -1; -} - -// Inter-thread and inter-process notifications of changes are done using a -// named pipe in the filesystem next to the Realm file. Everyone who wants to be -// notified of commits waits for data to become available on the pipe, and anyone -// who commits a write transaction writes data to the pipe after releasing the -// write lock. Note that no one ever actually *reads* from the pipe: the data -// actually written is meaningless, and trying to read from a pipe from multiple -// processes at once is fraught with race conditions. - -// When a RLMRealm instance is created, we add a CFRunLoopSource to the current -// thread's runloop. On each cycle of the run loop, the run loop checks each of -// its sources for work to do, which in the case of CFRunLoopSource is just -// checking if CFRunLoopSourceSignal has been called since the last time it ran, -// and if so invokes the function pointer supplied when the source is created, -// which in our case just invokes `[realm handleExternalChange]`. - -// Listening for external changes is done using kqueue() on a background thread. -// kqueue() lets us efficiently wait until the amount of data which can be read -// from one or more file descriptors has changed, and tells us which of the file -// descriptors it was that changed. We use this to wait on both the shared named -// pipe, and a local anonymous pipe. When data is written to the named pipe, we -// signal the runloop source and wake up the target runloop, and when data is -// written to the anonymous pipe the background thread removes the runloop -// source from the runloop and and shuts down. -ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) -: m_parent(parent) -{ - m_kq = kqueue(); - if (m_kq == -1) { - throw std::system_error(errno, std::system_category()); - } - -#if !TARGET_OS_TV - auto path = parent.get_path() + ".note"; - - // Create and open the named pipe - int ret = mkfifo(path.c_str(), 0600); - if (ret == -1) { - int err = errno; - if (err == ENOTSUP) { - // Filesystem doesn't support named pipes, so try putting it in tmp instead - // Hash collisions are okay here because they just result in doing - // extra work, as opposed to correctness problems - std::ostringstream ss; - ss << getenv("TMPDIR"); - ss << "realm_" << std::hash()(path) << ".note"; - path = ss.str(); - ret = mkfifo(path.c_str(), 0600); - err = errno; - } - // the fifo already existing isn't an error - if (ret == -1 && err != EEXIST) { - throw std::system_error(err, std::system_category()); - } - } - - m_notify_fd = open(path.c_str(), O_RDWR); - if (m_notify_fd == -1) { - throw std::system_error(errno, std::system_category()); - } - - // Make writing to the pipe return -1 when the pipe's buffer is full - // rather than blocking until there's space available - ret = fcntl(m_notify_fd, F_SETFL, O_NONBLOCK); - if (ret == -1) { - throw std::system_error(errno, std::system_category()); - } - -#else // !TARGET_OS_TV - - // tvOS does not support named pipes, so use an anonymous pipe instead - int notification_pipe[2]; - int ret = pipe(notification_pipe); - if (ret == -1) { - throw std::system_error(errno, std::system_category()); - } - - m_notify_fd = notification_pipe[0]; - m_notify_fd_write = notification_pipe[1]; - -#endif // TARGET_OS_TV - - // Create the anonymous pipe for shutdown notifications - int shutdown_pipe[2]; - ret = pipe(shutdown_pipe); - if (ret == -1) { - throw std::system_error(errno, std::system_category()); - } - - m_shutdown_read_fd = shutdown_pipe[0]; - m_shutdown_write_fd = shutdown_pipe[1]; - - m_thread = std::async(std::launch::async, [=] { - try { - listen(); - } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - catch (std::exception const& e) { - fprintf(stderr, "uncaught exception in notifier thread: %s: %s\n", typeid(e).name(), e.what()); - asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "uncaught exception in notifier thread: %s: %s", typeid(e).name(), e.what()); - throw; - } - catch (...) { - fprintf(stderr, "uncaught exception in notifier thread\n"); - asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "uncaught exception in notifier thread"); - throw; - } -#pragma clang diagnostic pop - }); -} - -ExternalCommitHelper::~ExternalCommitHelper() -{ - notify_fd(m_shutdown_write_fd, m_shutdown_read_fd); - m_thread.wait(); // Wait for the thread to exit -} - -void ExternalCommitHelper::listen() -{ - pthread_setname_np("RLMRealm notification listener"); - - // Set up the kqueue - // EVFILT_READ indicates that we care about data being available to read - // on the given file descriptor. - // EV_CLEAR makes it wait for the amount of data available to be read to - // change rather than just returning when there is any data to read. - struct kevent ke[2]; - EV_SET(&ke[0], m_notify_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0); - EV_SET(&ke[1], m_shutdown_read_fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0); - int ret = kevent(m_kq, ke, 2, nullptr, 0, nullptr); - assert(ret == 0); - - while (true) { - struct kevent event; - // Wait for data to become on either fd - // Return code is number of bytes available or -1 on error - ret = kevent(m_kq, nullptr, 0, &event, 1, nullptr); - assert(ret >= 0); - if (ret == 0) { - // Spurious wakeup; just wait again - continue; - } - - // Check which file descriptor had activity: if it's the shutdown - // pipe, then someone called -stop; otherwise it's the named pipe - // and someone committed a write transaction - if (event.ident == (uint32_t)m_shutdown_read_fd) { - return; - } - assert(event.ident == (uint32_t)m_notify_fd); - - m_parent.on_change(); - } -} - -void ExternalCommitHelper::notify_others() -{ - if (m_notify_fd_write != -1) { - notify_fd(m_notify_fd_write, m_notify_fd); - } - else { - notify_fd(m_notify_fd, m_notify_fd); - } -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp deleted file mode 100644 index b12128d..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/apple/keychain_helper.hpp" - -#include "util/format.hpp" - -#include -#include - -#include - -#include - -using realm::util::CFPtr; -using realm::util::adoptCF; - -namespace realm { -namespace keychain { - -KeychainAccessException::KeychainAccessException(int32_t error_code) -: std::runtime_error(util::format("Keychain returned unexpected status code: %1", error_code)) { } - -CFPtr convert_string(const std::string& string); -CFPtr build_search_dictionary(const std::string& account, const std::string& service, - util::Optional group); - -CFPtr convert_string(const std::string& string) -{ - auto result = adoptCF(CFStringCreateWithBytes(nullptr, reinterpret_cast(string.data()), - string.size(), kCFStringEncodingASCII, false)); - if (!result) { - throw std::bad_alloc(); - } - return result; -} - -CFPtr build_search_dictionary(const std::string& account, const std::string& service, - __unused util::Optional group) -{ - auto d = adoptCF(CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - if (!d) { - throw std::bad_alloc(); - } - CFDictionaryAddValue(d.get(), kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(d.get(), kSecReturnData, kCFBooleanTrue); - CFDictionaryAddValue(d.get(), kSecAttrAccessible, kSecAttrAccessibleAlways); - CFDictionaryAddValue(d.get(), kSecAttrAccount, convert_string(account).get()); - CFDictionaryAddValue(d.get(), kSecAttrService, convert_string(service).get()); -#if TARGET_IPHONE_SIMULATOR -#else - if (group) { - CFDictionaryAddValue(d.get(), kSecAttrAccessGroup, convert_string(*group).get()); - } -#endif - return d; -} - -std::vector metadata_realm_encryption_key() -{ - const size_t key_size = 64; - const std::string service = "io.realm.sync.keychain"; - const std::string account = "metadata"; - - auto search_dictionary = build_search_dictionary(account, service, none); - CFDataRef retained_key_data; - if (OSStatus status = SecItemCopyMatching(search_dictionary.get(), (CFTypeRef *)&retained_key_data)) { - if (status != errSecItemNotFound) { - throw KeychainAccessException(status); - } - - // Key was not found. Generate a new key, store it, and return it. - std::vector key(key_size); - arc4random_buf(key.data(), key_size); - auto key_data = adoptCF(CFDataCreate(nullptr, reinterpret_cast(key.data()), key_size)); - if (!key_data) { - throw std::bad_alloc(); - } - - CFDictionaryAddValue(search_dictionary.get(), kSecValueData, key_data.get()); - if (OSStatus status = SecItemAdd(search_dictionary.get(), nullptr)) { - throw KeychainAccessException(status); - } - - return key; - } - CFPtr key_data = adoptCF(retained_key_data); - - // Key was previously stored. Extract it. - if (key_size != CFDataGetLength(key_data.get())) { - throw std::runtime_error("Password stored in keychain was not expected size."); - } - - auto key_bytes = reinterpret_cast(CFDataGetBytePtr(key_data.get())); - return std::vector(key_bytes, key_bytes + key_size); -} - -} -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_change_builder.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_change_builder.cpp deleted file mode 100644 index 41e30df..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_change_builder.cpp +++ /dev/null @@ -1,806 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/collection_change_builder.hpp" - -#include -#include - -#include - -using namespace realm; -using namespace realm::_impl; - -CollectionChangeBuilder::CollectionChangeBuilder(IndexSet deletions, - IndexSet insertions, - IndexSet modifications, - std::vector moves) -: CollectionChangeSet({std::move(deletions), std::move(insertions), std::move(modifications), {}, std::move(moves)}) -{ - for (auto&& move : this->moves) { - this->deletions.add(move.from); - this->insertions.add(move.to); - } -} - -void CollectionChangeBuilder::merge(CollectionChangeBuilder&& c) -{ - if (c.empty()) - return; - if (empty()) { - *this = std::move(c); - return; - } - - verify(); - c.verify(); - - // First update any old moves - if (!c.moves.empty() || !c.deletions.empty() || !c.insertions.empty()) { - auto it = std::remove_if(begin(moves), end(moves), [&](auto& old) { - // Check if the moved row was moved again, and if so just update the destination - auto it = find_if(begin(c.moves), end(c.moves), [&](auto const& m) { - return old.to == m.from; - }); - if (it != c.moves.end()) { - if (modifications.contains(it->from)) - c.modifications.add(it->to); - old.to = it->to; - *it = c.moves.back(); - c.moves.pop_back(); - ++it; - return false; - } - - // Check if the destination was deleted - // Removing the insert for this move will happen later - if (c.deletions.contains(old.to)) - return true; - - // Update the destination to adjust for any new insertions and deletions - old.to = c.insertions.shift(c.deletions.unshift(old.to)); - return false; - }); - moves.erase(it, end(moves)); - } - - // Ignore new moves of rows which were previously inserted (the implicit - // delete from the move will remove the insert) - if (!insertions.empty() && !c.moves.empty()) { - c.moves.erase(std::remove_if(begin(c.moves), end(c.moves), - [&](auto const& m) { return insertions.contains(m.from); }), - end(c.moves)); - } - - // Ensure that any previously modified rows which were moved are still modified - if (!modifications.empty() && !c.moves.empty()) { - for (auto const& move : c.moves) { - if (modifications.contains(move.from)) - c.modifications.add(move.to); - } - } - - // Update the source position of new moves to compensate for the changes made - // in the old changeset - if (!deletions.empty() || !insertions.empty()) { - for (auto& move : c.moves) - move.from = deletions.shift(insertions.unshift(move.from)); - } - - moves.insert(end(moves), begin(c.moves), end(c.moves)); - - // New deletion indices have been shifted by the insertions, so unshift them - // before adding - deletions.add_shifted_by(insertions, c.deletions); - - // Drop any inserted-then-deleted rows, then merge in new insertions - insertions.erase_at(c.deletions); - insertions.insert_at(c.insertions); - - clean_up_stale_moves(); - - modifications.erase_at(c.deletions); - modifications.shift_for_insert_at(c.insertions); - modifications.add(c.modifications); - - c = {}; - verify(); -} - -void CollectionChangeBuilder::clean_up_stale_moves() -{ - // Look for moves which are now no-ops, and remove them plus the associated - // insert+delete. Note that this isn't just checking for from == to due to - // that rows can also be shifted by other inserts and deletes - moves.erase(std::remove_if(begin(moves), end(moves), [&](auto const& move) { - if (move.from - deletions.count(0, move.from) != move.to - insertions.count(0, move.to)) - return false; - deletions.remove(move.from); - insertions.remove(move.to); - return true; - }), end(moves)); -} - -void CollectionChangeBuilder::parse_complete() -{ - moves.reserve(m_move_mapping.size()); - for (auto move : m_move_mapping) { - REALM_ASSERT_DEBUG(deletions.contains(move.second)); - REALM_ASSERT_DEBUG(insertions.contains(move.first)); - if (move.first == move.second) { - deletions.remove(move.second); - insertions.remove(move.first); - } - else - moves.push_back({move.second, move.first}); - } - m_move_mapping.clear(); - std::sort(begin(moves), end(moves), - [](auto const& a, auto const& b) { return a.from < b.from; }); -} - -void CollectionChangeBuilder::modify(size_t ndx) -{ - modifications.add(ndx); -} - -void CollectionChangeBuilder::insert(size_t index, size_t count, bool track_moves) -{ - modifications.shift_for_insert_at(index, count); - if (!track_moves) - return; - - insertions.insert_at(index, count); - - for (auto& move : moves) { - if (move.to >= index) - ++move.to; - } -} - -void CollectionChangeBuilder::erase(size_t index) -{ - modifications.erase_at(index); - size_t unshifted = insertions.erase_or_unshift(index); - if (unshifted != IndexSet::npos) - deletions.add_shifted(unshifted); - - for (size_t i = 0; i < moves.size(); ++i) { - auto& move = moves[i]; - if (move.to == index) { - moves.erase(moves.begin() + i); - --i; - } - else if (move.to > index) - --move.to; - } -} - -void CollectionChangeBuilder::clear(size_t old_size) -{ - if (old_size != std::numeric_limits::max()) { - for (auto range : deletions) - old_size += range.second - range.first; - for (auto range : insertions) - old_size -= range.second - range.first; - } - - modifications.clear(); - insertions.clear(); - moves.clear(); - m_move_mapping.clear(); - deletions.set(old_size); -} - -void CollectionChangeBuilder::move(size_t from, size_t to) -{ - REALM_ASSERT(from != to); - - bool updated_existing_move = false; - for (auto& move : moves) { - if (move.to != from) { - // Shift other moves if this row is moving from one side of them - // to the other - if (move.to >= to && move.to < from) - ++move.to; - else if (move.to <= to && move.to > from) - --move.to; - continue; - } - REALM_ASSERT(!updated_existing_move); - - // Collapse A -> B, B -> C into a single A -> C move - move.to = to; - updated_existing_move = true; - - insertions.erase_at(from); - insertions.insert_at(to); - } - - if (!updated_existing_move) { - auto shifted_from = insertions.erase_or_unshift(from); - insertions.insert_at(to); - - // Don't report deletions/moves for newly inserted rows - if (shifted_from != IndexSet::npos) { - shifted_from = deletions.add_shifted(shifted_from); - moves.push_back({shifted_from, to}); - } - } - - bool modified = modifications.contains(from); - modifications.erase_at(from); - - if (modified) - modifications.insert_at(to); - else - modifications.shift_for_insert_at(to); -} - -void CollectionChangeBuilder::move_over(size_t row_ndx, size_t last_row, bool track_moves) -{ - REALM_ASSERT(row_ndx <= last_row); - REALM_ASSERT(insertions.empty() || prev(insertions.end())->second - 1 <= last_row); - REALM_ASSERT(modifications.empty() || prev(modifications.end())->second - 1 <= last_row); - - if (row_ndx == last_row) { - if (track_moves) { - auto shifted_from = insertions.erase_or_unshift(row_ndx); - if (shifted_from != IndexSet::npos) - deletions.add_shifted(shifted_from); - m_move_mapping.erase(row_ndx); - } - modifications.remove(row_ndx); - return; - } - - bool modified = modifications.contains(last_row); - if (modified) { - modifications.remove(last_row); - modifications.add(row_ndx); - } - else - modifications.remove(row_ndx); - - if (!track_moves) - return; - - bool row_is_insertion = insertions.contains(row_ndx); - bool last_is_insertion = !insertions.empty() && prev(insertions.end())->second == last_row + 1; - REALM_ASSERT_DEBUG(insertions.empty() || prev(insertions.end())->second <= last_row + 1); - - // Collapse A -> B, B -> C into a single A -> C move - bool last_was_already_moved = false; - if (last_is_insertion) { - auto it = m_move_mapping.find(last_row); - if (it != m_move_mapping.end() && it->first == last_row) { - m_move_mapping[row_ndx] = it->second; - m_move_mapping.erase(it); - last_was_already_moved = true; - } - } - - // Remove moves to the row being deleted - if (row_is_insertion && !last_was_already_moved) { - auto it = m_move_mapping.find(row_ndx); - if (it != m_move_mapping.end() && it->first == row_ndx) - m_move_mapping.erase(it); - } - - // Don't report deletions/moves if last_row is newly inserted - if (last_is_insertion) { - insertions.remove(last_row); - } - // If it was previously moved, the unshifted source row has already been marked as deleted - else if (!last_was_already_moved) { - auto shifted_last_row = insertions.unshift(last_row); - shifted_last_row = deletions.add_shifted(shifted_last_row); - m_move_mapping[row_ndx] = shifted_last_row; - } - - // Don't mark the moved-over row as deleted if it was a new insertion - if (!row_is_insertion) { - deletions.add_shifted(insertions.unshift(row_ndx)); - insertions.add(row_ndx); - } - verify(); -} - -void CollectionChangeBuilder::swap(size_t ndx_1, size_t ndx_2, bool track_moves) -{ - REALM_ASSERT(ndx_1 != ndx_2); - // The order of the two indices doesn't matter semantically, but making them - // consistent simplifies the logic - if (ndx_1 > ndx_2) - std::swap(ndx_1, ndx_2); - - bool row_1_modified = modifications.contains(ndx_1); - bool row_2_modified = modifications.contains(ndx_2); - if (row_1_modified != row_2_modified) { - if (row_1_modified) { - modifications.remove(ndx_1); - modifications.add(ndx_2); - } - else { - modifications.remove(ndx_2); - modifications.add(ndx_1); - } - } - - if (!track_moves) - return; - - auto update_move = [&](auto existing_it, auto ndx_1, auto ndx_2) { - // update the existing move to ndx_2 to point at ndx_1 - auto original = existing_it->second; - m_move_mapping.erase(existing_it); - m_move_mapping[ndx_1] = original; - - // add a move from 1 -> 2 unless 1 was a new insertion - if (!insertions.contains(ndx_1)) { - m_move_mapping[ndx_2] = deletions.add_shifted(insertions.unshift(ndx_1)); - insertions.add(ndx_1); - } - REALM_ASSERT_DEBUG(insertions.contains(ndx_2)); - }; - - auto move_1 = m_move_mapping.find(ndx_1); - auto move_2 = m_move_mapping.find(ndx_2); - bool have_move_1 = move_1 != end(m_move_mapping) && move_1->first == ndx_1; - bool have_move_2 = move_2 != end(m_move_mapping) && move_2->first == ndx_2; - if (have_move_1 && have_move_2) { - // both are already moves, so just swap the destinations - std::swap(move_1->second, move_2->second); - } - else if (have_move_1) { - update_move(move_1, ndx_2, ndx_1); - } - else if (have_move_2) { - update_move(move_2, ndx_1, ndx_2); - } - else { - // ndx_2 needs to be done before 1 to avoid incorrect shifting - if (!insertions.contains(ndx_2)) { - m_move_mapping[ndx_1] = deletions.add_shifted(insertions.unshift(ndx_2)); - insertions.add(ndx_2); - } - if (!insertions.contains(ndx_1)) { - m_move_mapping[ndx_2] = deletions.add_shifted(insertions.unshift(ndx_1)); - insertions.add(ndx_1); - } - } -} - -void CollectionChangeBuilder::subsume(size_t old_ndx, size_t new_ndx, bool track_moves) -{ - REALM_ASSERT(old_ndx != new_ndx); - - if (modifications.contains(old_ndx)) { - modifications.add(new_ndx); - } - - if (!track_moves) - return; - - REALM_ASSERT_DEBUG(insertions.contains(new_ndx)); - REALM_ASSERT_DEBUG(!m_move_mapping.count(new_ndx)); - - // If the source row was already moved, update the existing move - auto it = m_move_mapping.find(old_ndx); - if (it != m_move_mapping.end() && it->first == old_ndx) { - m_move_mapping[new_ndx] = it->second; - m_move_mapping.erase(it); - } - // otherwise add a new move unless it was a new insertion - else if (!insertions.contains(old_ndx)) { - m_move_mapping[new_ndx] = deletions.shift(insertions.unshift(old_ndx)); - } - - verify(); -} - -void CollectionChangeBuilder::verify() -{ -#ifdef REALM_DEBUG - for (auto&& move : moves) { - REALM_ASSERT(deletions.contains(move.from)); - REALM_ASSERT(insertions.contains(move.to)); - } -#endif -} - -namespace { -struct RowInfo { - size_t row_index; - size_t prev_tv_index; - size_t tv_index; - size_t shifted_tv_index; -}; - -// Calculates the insertions/deletions required for a query on a table without -// a sort, where `removed` includes the rows which were modified to no longer -// match the query (but not outright deleted rows, which are filtered out long -// before any of this logic), and `move_candidates` tracks the rows which may -// be the result of a move. -// -// This function is not strictly required, as calculate_moves_sorted() will -// produce correct results even for the scenarios where this function is used. -// However, this function has asymptotically better worst-case performance and -// extremely cheap best-case performance, and is guaranteed to produce a minimal -// diff when the only row moves are due to move_last_over(). -void calculate_moves_unsorted(std::vector& new_rows, IndexSet& removed, - IndexSet const& move_candidates, - CollectionChangeSet& changeset) -{ - // Here we track which row we expect to see, which in the absence of swap() - // is always the row immediately after the last row which was not moved. - size_t expected = 0; - for (auto& row : new_rows) { - if (row.shifted_tv_index == expected) { - ++expected; - continue; - } - - // We didn't find the row we were expecting to find, which means that - // either a row was moved forward to here, the row we were expecting was - // removed, or the row we were expecting moved back. - - // First check if this row even could have moved. If it can't, just - // treat it as a match and move on, and we'll handle the row we were - // expecting when we hit it later. - if (!move_candidates.contains(row.row_index)) { - expected = row.shifted_tv_index + 1; - continue; - } - - // Next calculate where we expect this row to be based on the insertions - // and removals (i.e. rows changed to not match the query), as it could - // be that the row actually ends up in this spot due to the rows before - // it being removed. - size_t calc_expected = row.tv_index - changeset.insertions.count(0, row.tv_index) + removed.count(0, row.prev_tv_index); - if (row.shifted_tv_index == calc_expected) { - expected = calc_expected + 1; - continue; - } - - // The row still isn't the expected one, so record it as a move - changeset.moves.push_back({row.prev_tv_index, row.tv_index}); - changeset.insertions.add(row.tv_index); - removed.add(row.prev_tv_index); - } -} - -class LongestCommonSubsequenceCalculator { -public: - // A pair of an index in the table and an index in the table view - struct Row { - size_t row_index; - size_t tv_index; - }; - - struct Match { - // The index in `a` at which this match begins - size_t i; - // The index in `b` at which this match begins - size_t j; - // The length of this match - size_t size; - // The number of rows in this block which were modified - size_t modified; - }; - std::vector m_longest_matches; - - LongestCommonSubsequenceCalculator(std::vector& a, std::vector& b, - size_t start_index, - IndexSet const& modifications) - : m_modified(modifications) - , a(a), b(b) - { - find_longest_matches(start_index, a.size(), - start_index, b.size()); - m_longest_matches.push_back({a.size(), b.size(), 0}); - } - -private: - IndexSet const& m_modified; - - // The two arrays of rows being diffed - // a is sorted by tv_index, b is sorted by row_index - std::vector &a, &b; - - // Find the longest matching range in (a + begin1, a + end1) and (b + begin2, b + end2) - // "Matching" is defined as "has the same row index"; the TV index is just - // there to let us turn an index in a/b into an index which can be reported - // in the output changeset. - // - // This is done with the O(N) space variant of the dynamic programming - // algorithm for longest common subsequence, where N is the maximum number - // of the most common row index (which for everything but linkview-derived - // TVs will be 1). - Match find_longest_match(size_t begin1, size_t end1, size_t begin2, size_t end2) - { - struct Length { - size_t j, len; - }; - // The length of the matching block for each `j` for the previously checked row - std::vector prev; - // The length of the matching block for each `j` for the row currently being checked - std::vector cur; - - // Calculate the length of the matching block *ending* at b[j], which - // is 1 if b[j - 1] did not match, and b[j - 1] + 1 otherwise. - auto length = [&](size_t j) -> size_t { - for (auto const& pair : prev) { - if (pair.j + 1 == j) - return pair.len + 1; - } - return 1; - }; - - // Iterate over each `j` which has the same row index as a[i] and falls - // within the range begin2 <= j < end2 - auto for_each_b_match = [&](size_t i, auto&& f) { - size_t ai = a[i].row_index; - // Find the TV indicies at which this row appears in the new results - // There should always be at least one (or it would have been - // filtered out earlier), but there can be multiple if there are dupes - auto it = lower_bound(begin(b), end(b), ai, - [](auto lft, auto rgt) { return lft.row_index < rgt; }); - REALM_ASSERT(it != end(b) && it->row_index == ai); - for (; it != end(b) && it->row_index == ai; ++it) { - size_t j = it->tv_index; - if (j < begin2) - continue; - if (j >= end2) - break; // b is sorted by tv_index so this can't transition from false to true - f(j); - } - }; - - Match best = {begin1, begin2, 0, 0}; - for (size_t i = begin1; i < end1; ++i) { - // prev = std::move(cur), but avoids discarding prev's heap allocation - cur.swap(prev); - cur.clear(); - - for_each_b_match(i, [&](size_t j) { - size_t size = length(j); - - cur.push_back({j, size}); - - // If the matching block ending at a[i] and b[j] is longer than - // the previous one, select it as the best - if (size > best.size) - best = {i - size + 1, j - size + 1, size, IndexSet::npos}; - // Given two equal-length matches, prefer the one with fewer modified rows - else if (size == best.size) { - if (best.modified == IndexSet::npos) - best.modified = m_modified.count(best.j - size + 1, best.j + 1); - auto count = m_modified.count(j - size + 1, j + 1); - if (count < best.modified) - best = {i - size + 1, j - size + 1, size, count}; - } - - // The best block should always fall within the range being searched - REALM_ASSERT(best.i >= begin1 && best.i + best.size <= end1); - REALM_ASSERT(best.j >= begin2 && best.j + best.size <= end2); - }); - } - return best; - } - - void find_longest_matches(size_t begin1, size_t end1, size_t begin2, size_t end2) - { - // FIXME: recursion could get too deep here - // recursion depth worst case is currently O(N) and each recursion uses 320 bytes of stack - // could reduce worst case to O(sqrt(N)) (and typical case to O(log N)) - // biasing equal selections towards the middle, but that's still - // insufficient for Android's 8 KB stacks - auto m = find_longest_match(begin1, end1, begin2, end2); - if (!m.size) - return; - if (m.i > begin1 && m.j > begin2) - find_longest_matches(begin1, m.i, begin2, m.j); - m_longest_matches.push_back(m); - if (m.i + m.size < end2 && m.j + m.size < end2) - find_longest_matches(m.i + m.size, end1, m.j + m.size, end2); - } -}; - -void calculate_moves_sorted(std::vector& rows, CollectionChangeSet& changeset) -{ - // The RowInfo array contains information about the old and new TV indices of - // each row, which we need to turn into two sequences of rows, which we'll - // then find matches in - std::vector a, b; - - a.reserve(rows.size()); - for (auto& row : rows) { - a.push_back({row.row_index, row.prev_tv_index}); - } - std::sort(begin(a), end(a), [](auto lft, auto rgt) { - return std::tie(lft.tv_index, lft.row_index) < std::tie(rgt.tv_index, rgt.row_index); - }); - - // Before constructing `b`, first find the first index in `a` which will - // actually differ in `b`, and skip everything else if there aren't any - size_t first_difference = IndexSet::npos; - for (size_t i = 0; i < a.size(); ++i) { - if (a[i].row_index != rows[i].row_index) { - first_difference = i; - break; - } - } - if (first_difference == IndexSet::npos) - return; - - // Note that `b` is sorted by row_index, while `a` is sorted by tv_index - b.reserve(rows.size()); - for (size_t i = 0; i < rows.size(); ++i) - b.push_back({rows[i].row_index, i}); - std::sort(begin(b), end(b), [](auto lft, auto rgt) { - return std::tie(lft.row_index, lft.tv_index) < std::tie(rgt.row_index, rgt.tv_index); - }); - - // Calculate the LCS of the two sequences - auto matches = LongestCommonSubsequenceCalculator(a, b, first_difference, - changeset.modifications).m_longest_matches; - - // And then insert and delete rows as needed to align them - size_t i = first_difference, j = first_difference; - for (auto match : matches) { - for (; i < match.i; ++i) - changeset.deletions.add(a[i].tv_index); - for (; j < match.j; ++j) - changeset.insertions.add(rows[j].tv_index); - i += match.size; - j += match.size; - } -} - -} // Anonymous namespace - -CollectionChangeBuilder CollectionChangeBuilder::calculate(std::vector const& prev_rows, - std::vector const& next_rows, - std::function row_did_change, - util::Optional const& move_candidates) -{ - REALM_ASSERT_DEBUG(!move_candidates || std::is_sorted(begin(next_rows), end(next_rows))); - - CollectionChangeBuilder ret; - - size_t deleted = 0; - std::vector old_rows; - old_rows.reserve(prev_rows.size()); - for (size_t i = 0; i < prev_rows.size(); ++i) { - if (prev_rows[i] == IndexSet::npos) { - ++deleted; - ret.deletions.add(i); - } - else - old_rows.push_back({prev_rows[i], IndexSet::npos, i, i - deleted}); - } - std::sort(begin(old_rows), end(old_rows), [](auto& lft, auto& rgt) { - return lft.row_index < rgt.row_index; - }); - - std::vector new_rows; - new_rows.reserve(next_rows.size()); - for (size_t i = 0; i < next_rows.size(); ++i) { - new_rows.push_back({next_rows[i], IndexSet::npos, i, 0}); - } - std::sort(begin(new_rows), end(new_rows), [](auto& lft, auto& rgt) { - return lft.row_index < rgt.row_index; - }); - - // Don't add rows which were modified to not match the query to `deletions` - // immediately because the unsorted move logic needs to be able to - // distinguish them from rows which were outright deleted - IndexSet removed; - - // Now that our old and new sets of rows are sorted by row index, we can - // iterate over them and either record old+new TV indices for rows present - // in both, or mark them as inserted/deleted if they appear only in one - size_t i = 0, j = 0; - while (i < old_rows.size() && j < new_rows.size()) { - auto old_index = old_rows[i]; - auto new_index = new_rows[j]; - if (old_index.row_index == new_index.row_index) { - new_rows[j].prev_tv_index = old_rows[i].tv_index; - new_rows[j].shifted_tv_index = old_rows[i].shifted_tv_index; - ++i; - ++j; - } - else if (old_index.row_index < new_index.row_index) { - removed.add(old_index.tv_index); - ++i; - } - else { - ret.insertions.add(new_index.tv_index); - ++j; - } - } - - for (; i < old_rows.size(); ++i) - removed.add(old_rows[i].tv_index); - for (; j < new_rows.size(); ++j) - ret.insertions.add(new_rows[j].tv_index); - - // Filter out the new insertions since we don't need them for any of the - // further calculations - new_rows.erase(std::remove_if(begin(new_rows), end(new_rows), - [](auto& row) { return row.prev_tv_index == IndexSet::npos; }), - end(new_rows)); - std::sort(begin(new_rows), end(new_rows), - [](auto& lft, auto& rgt) { return lft.tv_index < rgt.tv_index; }); - - for (auto& row : new_rows) { - if (row_did_change(row.row_index)) { - ret.modifications.add(row.tv_index); - } - } - - if (move_candidates) { - calculate_moves_unsorted(new_rows, removed, *move_candidates, ret); - } - else { - calculate_moves_sorted(new_rows, ret); - } - ret.deletions.add(removed); - ret.verify(); - -#ifdef REALM_DEBUG - { // Verify that applying the calculated change to prev_rows actually produces next_rows - auto rows = prev_rows; - auto it = util::make_reverse_iterator(ret.deletions.end()); - auto end = util::make_reverse_iterator(ret.deletions.begin()); - for (; it != end; ++it) { - rows.erase(rows.begin() + it->first, rows.begin() + it->second); - } - - for (auto i : ret.insertions.as_indexes()) { - rows.insert(rows.begin() + i, next_rows[i]); - } - - REALM_ASSERT(rows == next_rows); - } -#endif - - return ret; -} - -CollectionChangeSet CollectionChangeBuilder::finalize() && -{ - // Calculate which indices in the old collection were modified - auto modifications_in_old = modifications; - modifications_in_old.erase_at(insertions); - modifications_in_old.shift_for_insert_at(deletions); - - // During changeset calculation we allow marking a row as both inserted and - // modified in case changeset merging results in it no longer being an insert, - // but we don't want inserts in the final modification set - modifications.remove(insertions); - - return { - std::move(deletions), - std::move(insertions), - std::move(modifications_in_old), - std::move(modifications), - std::move(moves) - }; -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp deleted file mode 100644 index f6e9184..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp +++ /dev/null @@ -1,469 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/collection_notifier.hpp" - -#include "impl/realm_coordinator.hpp" -#include "shared_realm.hpp" - -#include -#include - -using namespace realm; -using namespace realm::_impl; - -std::function -CollectionNotifier::get_modification_checker(TransactionChangeInfo const& info, - Table const& root_table) -{ - // First check if any of the tables accessible from the root table were - // actually modified. This can be false if there were only insertions, or - // deletions which were not linked to by any row in the linking table - auto table_modified = [&](auto& tbl) { - return tbl.table_ndx < info.tables.size() - && !info.tables[tbl.table_ndx].modifications.empty(); - }; - if (!any_of(begin(m_related_tables), end(m_related_tables), table_modified)) { - return [](size_t) { return false; }; - } - - return DeepChangeChecker(info, root_table, m_related_tables); -} - -void DeepChangeChecker::find_related_tables(std::vector& out, Table const& table) -{ - auto table_ndx = table.get_index_in_group(); - if (any_of(begin(out), end(out), [=](auto& tbl) { return tbl.table_ndx == table_ndx; })) - return; - - // We need to add this table to `out` before recurring so that the check - // above works, but we can't store a pointer to the thing being populated - // because the recursive calls may resize `out`, so instead look it up by - // index every time - size_t out_index = out.size(); - out.push_back({table_ndx, {}}); - - for (size_t i = 0, count = table.get_column_count(); i != count; ++i) { - auto type = table.get_column_type(i); - if (type == type_Link || type == type_LinkList) { - out[out_index].links.push_back({i, type == type_LinkList}); - find_related_tables(out, *table.get_link_target(i)); - } - } -} - -DeepChangeChecker::DeepChangeChecker(TransactionChangeInfo const& info, - Table const& root_table, - std::vector const& related_tables) -: m_info(info) -, m_root_table(root_table) -, m_root_table_ndx(root_table.get_index_in_group()) -, m_root_modifications(m_root_table_ndx < info.tables.size() ? &info.tables[m_root_table_ndx].modifications : nullptr) -, m_related_tables(related_tables) -{ -} - -bool DeepChangeChecker::check_outgoing_links(size_t table_ndx, - Table const& table, - size_t row_ndx, size_t depth) -{ - auto it = find_if(begin(m_related_tables), end(m_related_tables), - [&](auto&& tbl) { return tbl.table_ndx == table_ndx; }); - if (it == m_related_tables.end()) - return false; - - // Check if we're already checking if the destination of the link is - // modified, and if not add it to the stack - auto already_checking = [&](size_t col) { - for (auto p = m_current_path.begin(); p < m_current_path.begin() + depth; ++p) { - if (p->table == table_ndx && p->row == row_ndx && p->col == col) - return true; - } - m_current_path[depth] = {table_ndx, row_ndx, col, false}; - return false; - }; - - for (auto const& link : it->links) { - if (already_checking(link.col_ndx)) - continue; - if (!link.is_list) { - if (table.is_null_link(link.col_ndx, row_ndx)) - continue; - auto dst = table.get_link(link.col_ndx, row_ndx); - return check_row(*table.get_link_target(link.col_ndx), dst, depth + 1); - } - - auto& target = *table.get_link_target(link.col_ndx); - auto lvr = table.get_linklist(link.col_ndx, row_ndx); - for (size_t j = 0, size = lvr->size(); j < size; ++j) { - size_t dst = lvr->get(j).get_index(); - if (check_row(target, dst, depth + 1)) - return true; - } - } - - return false; -} - -bool DeepChangeChecker::check_row(Table const& table, size_t idx, size_t depth) -{ - // Arbitrary upper limit on the maximum depth to search - if (depth >= m_current_path.size()) { - // Don't mark any of the intermediate rows checked along the path as - // not modified, as a search starting from them might hit a modification - for (size_t i = 1; i < m_current_path.size(); ++i) - m_current_path[i].depth_exceeded = true; - return false; - } - - size_t table_ndx = table.get_index_in_group(); - if (depth > 0 && table_ndx < m_info.tables.size() && m_info.tables[table_ndx].modifications.contains(idx)) - return true; - - if (m_not_modified.size() <= table_ndx) - m_not_modified.resize(table_ndx + 1); - if (m_not_modified[table_ndx].contains(idx)) - return false; - - bool ret = check_outgoing_links(table_ndx, table, idx, depth); - if (!ret && !m_current_path[depth].depth_exceeded) - m_not_modified[table_ndx].add(idx); - return ret; -} - -bool DeepChangeChecker::operator()(size_t ndx) -{ - if (m_root_modifications && m_root_modifications->contains(ndx)) - return true; - return check_row(m_root_table, ndx, 0); -} - -CollectionNotifier::CollectionNotifier(std::shared_ptr realm) -: m_realm(std::move(realm)) -, m_sg_version(Realm::Internal::get_shared_group(*m_realm).get_version_of_current_transaction()) -{ -} - -CollectionNotifier::~CollectionNotifier() -{ - // Need to do this explicitly to ensure m_realm is destroyed with the mutex - // held to avoid potential double-deletion - unregister(); -} - -size_t CollectionNotifier::add_callback(CollectionChangeCallback callback) -{ - m_realm->verify_thread(); - - auto next_token = [=] { - size_t token = 0; - for (auto& callback : m_callbacks) { - if (token <= callback.token) { - token = callback.token + 1; - } - } - return token; - }; - - std::lock_guard lock(m_callback_mutex); - auto token = next_token(); - m_callbacks.push_back({std::move(callback), {}, {}, token, false, false}); - if (m_callback_index == npos) { // Don't need to wake up if we're already sending notifications - Realm::Internal::get_coordinator(*m_realm).wake_up_notifier_worker(); - m_have_callbacks = true; - } - return token; -} - -void CollectionNotifier::remove_callback(size_t token) -{ - // the callback needs to be destroyed after releasing the lock as destroying - // it could cause user code to be called - Callback old; - { - std::lock_guard lock(m_callback_mutex); - auto it = find_callback(token); - if (it == end(m_callbacks)) { - return; - } - - size_t idx = distance(begin(m_callbacks), it); - if (m_callback_index != npos && m_callback_index >= idx) { - --m_callback_index; - } - - old = std::move(*it); - m_callbacks.erase(it); - - m_have_callbacks = !m_callbacks.empty(); - } -} - -void CollectionNotifier::suppress_next_notification(size_t token) -{ - { - std::lock_guard lock(m_realm_mutex); - REALM_ASSERT(m_realm); - m_realm->verify_thread(); - m_realm->verify_in_write(); - } - - std::lock_guard lock(m_callback_mutex); - auto it = find_callback(token); - if (it != end(m_callbacks)) { - it->skip_next = true; - } -} - -std::vector::iterator CollectionNotifier::find_callback(size_t token) -{ - REALM_ASSERT(m_error || m_callbacks.size() > 0); - - auto it = find_if(begin(m_callbacks), end(m_callbacks), - [=](const auto& c) { return c.token == token; }); - // We should only fail to find the callback if it was removed due to an error - REALM_ASSERT(m_error || it != end(m_callbacks)); - return it; -} - -void CollectionNotifier::unregister() noexcept -{ - std::lock_guard lock(m_realm_mutex); - m_realm = nullptr; -} - -bool CollectionNotifier::is_alive() const noexcept -{ - std::lock_guard lock(m_realm_mutex); - return m_realm != nullptr; -} - -std::unique_lock CollectionNotifier::lock_target() -{ - return std::unique_lock{m_realm_mutex}; -} - -void CollectionNotifier::set_table(Table const& table) -{ - m_related_tables.clear(); - DeepChangeChecker::find_related_tables(m_related_tables, table); -} - -void CollectionNotifier::add_required_change_info(TransactionChangeInfo& info) -{ - if (!do_add_required_change_info(info)) { - return; - } - - auto max = max_element(begin(m_related_tables), end(m_related_tables), - [](auto&& a, auto&& b) { return a.table_ndx < b.table_ndx; }); - - if (max->table_ndx >= info.table_modifications_needed.size()) - info.table_modifications_needed.resize(max->table_ndx + 1, false); - for (auto& tbl : m_related_tables) { - info.table_modifications_needed[tbl.table_ndx] = true; - } -} - -void CollectionNotifier::prepare_handover() -{ - REALM_ASSERT(m_sg); - m_sg_version = m_sg->get_version_of_current_transaction(); - do_prepare_handover(*m_sg); - m_has_run = true; -} - -void CollectionNotifier::before_advance() -{ - for_each_callback([&](auto& lock, auto& callback) { - if (callback.changes_to_deliver.empty()) { - return; - } - - auto changes = callback.changes_to_deliver; - // acquire a local reference to the callback so that removing the - // callback from within it can't result in a dangling pointer - auto cb = callback.fn; - lock.unlock(); - cb.before(changes); - }); -} - -void CollectionNotifier::after_advance() -{ - for_each_callback([&](auto& lock, auto& callback) { - if (callback.initial_delivered && callback.changes_to_deliver.empty()) { - return; - } - callback.initial_delivered = true; - - auto changes = std::move(callback.changes_to_deliver); - // acquire a local reference to the callback so that removing the - // callback from within it can't result in a dangling pointer - auto cb = callback.fn; - lock.unlock(); - cb.after(changes); - }); -} - -void CollectionNotifier::deliver_error(std::exception_ptr error) -{ - for_each_callback([&](auto& lock, auto& callback) { - // acquire a local reference to the callback so that removing the - // callback from within it can't result in a dangling pointer - auto cb = callback.fn; - lock.unlock(); - cb.error(error); - }); - - // Remove all the callbacks as we never need to call anything ever again - // after delivering an error - m_callbacks.clear(); - m_error = true; -} - -bool CollectionNotifier::is_for_realm(Realm& realm) const noexcept -{ - std::lock_guard lock(m_realm_mutex); - return m_realm.get() == &realm; -} - -bool CollectionNotifier::package_for_delivery() -{ - if (!prepare_to_deliver()) - return false; - std::lock_guard l(m_callback_mutex); - for (auto& callback : m_callbacks) - callback.changes_to_deliver = std::move(callback.accumulated_changes).finalize(); - return true; -} - -template -void CollectionNotifier::for_each_callback(Fn&& fn) -{ - std::unique_lock callback_lock(m_callback_mutex); - for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) { - fn(callback_lock, m_callbacks[m_callback_index]); - if (!callback_lock.owns_lock()) - callback_lock.lock(); - } - - m_callback_index = npos; -} - -void CollectionNotifier::attach_to(SharedGroup& sg) -{ - REALM_ASSERT(!m_sg); - - m_sg = &sg; - do_attach_to(sg); -} - -void CollectionNotifier::detach() -{ - REALM_ASSERT(m_sg); - do_detach_from(*m_sg); - m_sg = nullptr; -} - -void CollectionNotifier::add_changes(CollectionChangeBuilder change) -{ - std::lock_guard lock(m_callback_mutex); - for (auto& callback : m_callbacks) { - if (callback.skip_next) { - REALM_ASSERT_DEBUG(callback.accumulated_changes.empty()); - callback.skip_next = false; - } - else { - if (&callback == &m_callbacks.back()) - callback.accumulated_changes.merge(std::move(change)); - else - callback.accumulated_changes.merge(CollectionChangeBuilder(change)); - } - } -} - -NotifierPackage::NotifierPackage(std::exception_ptr error, - std::vector> notifiers, - RealmCoordinator* coordinator) -: m_notifiers(std::move(notifiers)) -, m_coordinator(coordinator) -, m_error(std::move(error)) -{ -} - -void NotifierPackage::package_and_wait(util::Optional target_version) -{ - if (!m_coordinator || m_error || !*this) - return; - - auto lock = m_coordinator->wait_for_notifiers([&] { - if (!target_version) - return true; - return std::all_of(begin(m_notifiers), end(m_notifiers), [&](auto const& n) { - return !n->have_callbacks() || (n->has_run() && n->version().version >= *target_version); - }); - }); - - // Package the notifiers for delivery and remove any which don't have anything to deliver - auto package = [&](auto& notifier) { - if (notifier->has_run() && notifier->package_for_delivery()) { - m_version = notifier->version(); - return false; - } - return true; - }; - m_notifiers.erase(std::remove_if(begin(m_notifiers), end(m_notifiers), package), end(m_notifiers)); - if (m_version && target_version && m_version->version < *target_version) { - m_notifiers.clear(); - m_version = util::none; - } - REALM_ASSERT(m_version || m_notifiers.empty()); - - m_coordinator = nullptr; -} - -void NotifierPackage::before_advance() -{ - if (m_error) - return; - for (auto& notifier : m_notifiers) - notifier->before_advance(); -} - -void NotifierPackage::deliver(SharedGroup& sg) -{ - if (m_error) { - for (auto& notifier : m_notifiers) - notifier->deliver_error(m_error); - return; - } - // Can't deliver while in a write transaction - if (sg.get_transact_stage() != SharedGroup::transact_Reading) - return; - for (auto& notifier : m_notifiers) - notifier->deliver(sg); -} - -void NotifierPackage::after_advance() -{ - if (m_error) - return; - for (auto& notifier : m_notifiers) - notifier->after_advance(); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/handover.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/handover.cpp deleted file mode 100644 index 41a8a0e..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/handover.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/handover.hpp" - -using namespace realm; -using namespace realm::_impl; - -AnyHandover::AnyHandover(AnyHandover&& handover) -{ - switch (handover.m_type) { - case AnyThreadConfined::Type::Object: - new (&m_object.row_handover) RowHandover(std::move(handover.m_object.row_handover)); - new (&m_object.object_schema_name) std::string(std::move(handover.m_object.object_schema_name)); - break; - - case AnyThreadConfined::Type::List: - new (&m_list.link_view_handover) LinkViewHandover(std::move(handover.m_list.link_view_handover)); - break; - - case AnyThreadConfined::Type::Results: - new (&m_results.query_handover) QueryHandover(std::move(handover.m_results.query_handover)); - new (&m_results.sort_order) SortDescriptor::HandoverPatch(std::move(handover.m_results.sort_order)); - break; - } - new (&m_type) AnyThreadConfined::Type(handover.m_type); -} - -AnyHandover& AnyHandover::operator=(AnyHandover&& handover) -{ - this->~AnyHandover(); - new (this) AnyHandover(std::move(handover)); - return *this; -} - -AnyHandover::~AnyHandover() -{ - switch (m_type) { - case AnyThreadConfined::Type::Object: - m_object.row_handover.~unique_ptr(); - break; - - case AnyThreadConfined::Type::List: - m_list.link_view_handover.~unique_ptr(); - break; - - case AnyThreadConfined::Type::Results: - m_results.query_handover.~unique_ptr(); - m_results.sort_order.~unique_ptr(); - break; - } -} - -AnyThreadConfined AnyHandover::import_from_handover(SharedRealm realm) && -{ - SharedGroup& shared_group = Realm::Internal::get_shared_group(*realm); - switch (m_type) { - case AnyThreadConfined::Type::Object: { - auto row = shared_group.import_from_handover(std::move(m_object.row_handover)); - auto object_schema = realm->schema().find(m_object.object_schema_name); - REALM_ASSERT_DEBUG(object_schema != realm->schema().end()); - return AnyThreadConfined(Object(std::move(realm), *object_schema, std::move(*row))); - } - case AnyThreadConfined::Type::List: { - auto link_view_ref = shared_group.import_linkview_from_handover(std::move(m_list.link_view_handover)); - return AnyThreadConfined(List(std::move(realm), std::move(link_view_ref))); - } - case AnyThreadConfined::Type::Results: { - auto query = shared_group.import_from_handover(std::move(m_results.query_handover)); - auto& table = *query->get_table(); - return AnyThreadConfined(Results(std::move(realm), std::move(*query), - SortDescriptor::create_from_and_consume_patch(m_results.sort_order, table))); - } - } - REALM_UNREACHABLE(); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/list_notifier.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/list_notifier.cpp deleted file mode 100644 index beec1d5..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/list_notifier.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/list_notifier.hpp" - -#include "shared_realm.hpp" - -#include - -using namespace realm; -using namespace realm::_impl; - -ListNotifier::ListNotifier(LinkViewRef lv, std::shared_ptr realm) -: CollectionNotifier(std::move(realm)) -, m_prev_size(lv->size()) -{ - set_table(lv->get_target_table()); - - auto& sg = Realm::Internal::get_shared_group(*get_realm()); - m_lv_handover = sg.export_linkview_for_handover(lv); -} - -void ListNotifier::release_data() noexcept -{ - m_lv.reset(); -} - -void ListNotifier::do_attach_to(SharedGroup& sg) -{ - REALM_ASSERT(m_lv_handover); - REALM_ASSERT(!m_lv); - m_lv = sg.import_linkview_from_handover(std::move(m_lv_handover)); -} - -void ListNotifier::do_detach_from(SharedGroup& sg) -{ - REALM_ASSERT(!m_lv_handover); - if (m_lv) { - m_lv_handover = sg.export_linkview_for_handover(m_lv); - m_lv = {}; - } -} - -bool ListNotifier::do_add_required_change_info(TransactionChangeInfo& info) -{ - REALM_ASSERT(!m_lv_handover); - if (!m_lv || !m_lv->is_attached()) { - return false; // origin row was deleted after the notification was added - } - - // Find the lv's column, since that isn't tracked directly - auto& table = m_lv->get_origin_table(); - size_t row_ndx = m_lv->get_origin_row_index(); - size_t col_ndx = not_found; - for (size_t i = 0, count = table.get_column_count(); i != count; ++i) { - if (table.get_column_type(i) == type_LinkList && table.get_linklist(i, row_ndx) == m_lv) { - col_ndx = i; - break; - } - } - REALM_ASSERT(col_ndx != not_found); - info.lists.push_back({table.get_index_in_group(), row_ndx, col_ndx, &m_change}); - - m_info = &info; - return true; -} - -void ListNotifier::run() -{ - if (!m_lv || !m_lv->is_attached()) { - // LV was deleted, so report all of the rows being removed if this is - // the first run after that - if (m_prev_size) { - m_change.deletions.set(m_prev_size); - m_prev_size = 0; - } - else { - m_change = {}; - } - return; - } - - auto row_did_change = get_modification_checker(*m_info, m_lv->get_target_table()); - for (size_t i = 0; i < m_lv->size(); ++i) { - if (m_change.modifications.contains(i)) - continue; - if (row_did_change(m_lv->get(i).get_index())) - m_change.modifications.add(i); - } - - for (auto const& move : m_change.moves) { - if (m_change.modifications.contains(move.to)) - continue; - if (row_did_change(m_lv->get(move.to).get_index())) - m_change.modifications.add(move.to); - } - - m_prev_size = m_lv->size(); -} - -void ListNotifier::do_prepare_handover(SharedGroup&) -{ - add_changes(std::move(m_change)); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp deleted file mode 100644 index ebb2772..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp +++ /dev/null @@ -1,756 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/realm_coordinator.hpp" - -#include "impl/collection_notifier.hpp" -#include "impl/external_commit_helper.hpp" -#include "impl/transact_log_handler.hpp" -#include "impl/weak_realm_notifier.hpp" -#include "binding_context.hpp" -#include "object_schema.hpp" -#include "object_store.hpp" -#include "schema.hpp" - -#if REALM_ENABLE_SYNC -#include "sync/sync_config.hpp" -#include "sync/sync_manager.hpp" -#include "sync/sync_session.hpp" -#endif - -#include -#include -#include - -#include -#include - -using namespace realm; -using namespace realm::_impl; - -static std::mutex s_coordinator_mutex; -static std::unordered_map> s_coordinators_per_path; - -std::shared_ptr RealmCoordinator::get_coordinator(StringData path) -{ - std::lock_guard lock(s_coordinator_mutex); - - auto& weak_coordinator = s_coordinators_per_path[path]; - if (auto coordinator = weak_coordinator.lock()) { - return coordinator; - } - - auto coordinator = std::make_shared(); - weak_coordinator = coordinator; - return coordinator; -} - -std::shared_ptr RealmCoordinator::get_coordinator(const Realm::Config& config) -{ - auto coordinator = get_coordinator(config.path); - std::lock_guard lock(coordinator->m_realm_mutex); - coordinator->set_config(config); - return coordinator; -} - -std::shared_ptr RealmCoordinator::get_existing_coordinator(StringData path) -{ - std::lock_guard lock(s_coordinator_mutex); - auto it = s_coordinators_per_path.find(path); - return it == s_coordinators_per_path.end() ? nullptr : it->second.lock(); -} - -void RealmCoordinator::create_sync_session() -{ -#if REALM_ENABLE_SYNC - if (m_sync_session) - return; - - m_sync_session = SyncManager::shared().get_session(m_config.path, *m_config.sync_config); - - std::weak_ptr weak_self = shared_from_this(); - SyncSession::Internal::set_sync_transact_callback(*m_sync_session, - [weak_self](VersionID old_version, VersionID new_version) { - if (auto self = weak_self.lock()) { - if (self->m_transaction_callback) - self->m_transaction_callback(old_version, new_version); - if (self->m_notifier) - self->m_notifier->notify_others(); - } - }); - if (m_config.sync_config->error_handler) { - SyncSession::Internal::set_error_handler(*m_sync_session, m_config.sync_config->error_handler); - } -#endif -} - -void RealmCoordinator::set_config(const Realm::Config& config) -{ - if ((!m_config.read_only() && !m_notifier) || (m_config.read_only() && m_weak_realm_notifiers.empty())) { - m_config = config; - } - else { - if (m_config.read_only() != config.read_only()) { - throw MismatchedConfigException("Realm at path '%1' already opened with different read permissions.", config.path); - } - if (m_config.in_memory != config.in_memory) { - throw MismatchedConfigException("Realm at path '%1' already opened with different inMemory settings.", config.path); - } - if (m_config.encryption_key != config.encryption_key) { - throw MismatchedConfigException("Realm at path '%1' already opened with a different encryption key.", config.path); - } - if (m_config.schema_mode != config.schema_mode) { - throw MismatchedConfigException("Realm at path '%1' already opened with a different schema mode.", config.path); - } - if (m_config.schema_version != config.schema_version && config.schema_version != ObjectStore::NotVersioned) { - throw MismatchedConfigException("Realm at path '%1' already opened with different schema version.", config.path); - } - -#if REALM_ENABLE_SYNC - if (bool(m_config.sync_config) != bool(config.sync_config)) { - throw MismatchedConfigException("Realm at path '%1' already opened with different sync configurations.", config.path); - } - - if (config.sync_config) { - if (m_config.sync_config->user != config.sync_config->user) { - throw MismatchedConfigException("Realm at path '%1' already opened with different sync user.", config.path); - } - if (m_config.sync_config->realm_url != config.sync_config->realm_url) { - throw MismatchedConfigException("Realm at path '%1' already opened with different sync server URL.", config.path); - } - } -#endif - - // Realm::update_schema() handles complaining about schema mismatches - } - -#if REALM_ENABLE_SYNC - if (config.sync_config) { - create_sync_session(); - } -#endif -} - -std::shared_ptr RealmCoordinator::get_realm(Realm::Config config) -{ - std::lock_guard lock(m_realm_mutex); - - set_config(config); - - if (config.cache) { - for (auto& cached_realm : m_weak_realm_notifiers) { - if (cached_realm.is_cached_for_current_thread()) { - // can be null if we jumped in between ref count hitting zero and - // unregister_realm() getting the lock - if (auto realm = cached_realm.realm()) { - return realm; - } - } - } - } - - auto realm = Realm::make_shared_realm(std::move(config)); - if (!config.read_only() && !m_notifier && config.automatic_change_notifications) { - try { - m_notifier = std::make_unique(*this); - } - catch (std::system_error const& ex) { - throw RealmFileException(RealmFileException::Kind::AccessError, config.path, ex.code().message(), ""); - } - } - realm->init(shared_from_this()); - - m_weak_realm_notifiers.emplace_back(realm, m_config.cache); - return realm; -} - -std::shared_ptr RealmCoordinator::get_realm() -{ - return get_realm(m_config); -} - -const Schema* RealmCoordinator::get_schema() const noexcept -{ - return m_schema_version == uint64_t(-1) ? nullptr : &m_schema; -} - -void RealmCoordinator::update_schema(Schema const& schema, uint64_t schema_version) -{ - if (m_schema_version != uint64_t(-1) && m_schema_version != schema_version && m_weak_realm_notifiers.size() > 1) { - throw MismatchedConfigException("Realm at path '%1' already opened with a different schema version.", m_config.path); - } - - m_schema = schema; - m_schema_version = schema_version; - - // FIXME: notify realms of the schema change -} - -RealmCoordinator::RealmCoordinator() = default; - -RealmCoordinator::~RealmCoordinator() -{ - std::lock_guard coordinator_lock(s_coordinator_mutex); - for (auto it = s_coordinators_per_path.begin(); it != s_coordinators_per_path.end(); ) { - if (it->second.expired()) { - it = s_coordinators_per_path.erase(it); - } - else { - ++it; - } - } -} - -void RealmCoordinator::unregister_realm(Realm* realm) -{ - std::lock_guard lock(m_realm_mutex); - auto new_end = remove_if(begin(m_weak_realm_notifiers), end(m_weak_realm_notifiers), - [=](auto& notifier) { return notifier.expired() || notifier.is_for_realm(realm); }); - m_weak_realm_notifiers.erase(new_end, end(m_weak_realm_notifiers)); -} - -void RealmCoordinator::clear_cache() -{ - std::vector realms_to_close; - { - std::lock_guard lock(s_coordinator_mutex); - - for (auto& weak_coordinator : s_coordinators_per_path) { - auto coordinator = weak_coordinator.second.lock(); - if (!coordinator) { - continue; - } - - coordinator->m_notifier = nullptr; - - // Gather a list of all of the realms which will be removed - for (auto& weak_realm_notifier : coordinator->m_weak_realm_notifiers) { - if (auto realm = weak_realm_notifier.realm()) { - realms_to_close.push_back(realm); - } - } - } - - s_coordinators_per_path.clear(); - } - - // Close all of the previously cached Realms. This can't be done while - // s_coordinator_mutex is held as it may try to re-lock it. - for (auto& weak_realm : realms_to_close) { - if (auto realm = weak_realm.lock()) { - realm->close(); - } - } -} - -void RealmCoordinator::clear_all_caches() -{ - std::vector> to_clear; - { - std::lock_guard lock(s_coordinator_mutex); - for (auto iter : s_coordinators_per_path) { - to_clear.push_back(iter.second); - } - } - for (auto weak_coordinator : to_clear) { - if (auto coordinator = weak_coordinator.lock()) { - coordinator->clear_cache(); - } - } -} - -void RealmCoordinator::wake_up_notifier_worker() -{ - if (m_notifier) { - // FIXME: this wakes up the notification workers for all processes and - // not just us. This might be worth optimizing in the future. - m_notifier->notify_others(); - } -} - -void RealmCoordinator::commit_write(Realm& realm) -{ - REALM_ASSERT(!m_config.read_only()); - REALM_ASSERT(realm.is_in_transaction()); - - { - // Need to acquire this lock before committing or another process could - // perform a write and notify us before we get the chance to set the - // skip version - std::lock_guard l(m_notifier_mutex); - - transaction::commit(Realm::Internal::get_shared_group(realm)); - - // Don't need to check m_new_notifiers because those don't skip versions - bool have_notifiers = std::any_of(m_notifiers.begin(), m_notifiers.end(), - [&](auto&& notifier) { return notifier->is_for_realm(realm); }); - if (have_notifiers) { - m_notifier_skip_version = Realm::Internal::get_shared_group(realm).get_version_of_current_transaction(); - } - } - - if (realm.m_binding_context) { - realm.m_binding_context->did_change({}, {}); - } - - if (m_notifier) { - m_notifier->notify_others(); - } -#if REALM_ENABLE_SYNC - if (m_sync_session) { - auto& sg = Realm::Internal::get_shared_group(realm); - auto version = LangBindHelper::get_version_of_latest_snapshot(sg); - SyncSession::Internal::nonsync_transact_notify(*m_sync_session, version); - } -#endif -} - -void RealmCoordinator::pin_version(VersionID versionid) -{ - REALM_ASSERT_DEBUG(!m_notifier_mutex.try_lock()); - if (m_async_error) { - return; - } - - if (!m_advancer_sg) { - try { - std::unique_ptr read_only_group; - Realm::open_with_config(m_config, m_advancer_history, m_advancer_sg, read_only_group, nullptr); - REALM_ASSERT(!read_only_group); - m_advancer_sg->begin_read(versionid); - } - catch (...) { - m_async_error = std::current_exception(); - m_advancer_sg = nullptr; - m_advancer_history = nullptr; - } - } - else if (m_new_notifiers.empty()) { - // If this is the first notifier then we don't already have a read transaction - REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Ready); - m_advancer_sg->begin_read(versionid); - } - else { - REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading); - if (versionid < m_advancer_sg->get_version_of_current_transaction()) { - // Ensure we're holding a readlock on the oldest version we have a - // handover object for, as handover objects don't - m_advancer_sg->end_read(); - m_advancer_sg->begin_read(versionid); - } - } -} - -void RealmCoordinator::register_notifier(std::shared_ptr notifier) -{ - auto version = notifier->version(); - auto& self = Realm::Internal::get_coordinator(*notifier->get_realm()); - { - std::lock_guard lock(self.m_notifier_mutex); - self.pin_version(version); - self.m_new_notifiers.push_back(std::move(notifier)); - } -} - -void RealmCoordinator::clean_up_dead_notifiers() -{ - auto swap_remove = [&](auto& container) { - bool did_remove = false; - for (size_t i = 0; i < container.size(); ++i) { - if (container[i]->is_alive()) - continue; - - // Ensure the notifier is destroyed here even if there's lingering refs - // to the async notifier elsewhere - container[i]->release_data(); - - if (container.size() > i + 1) - container[i] = std::move(container.back()); - container.pop_back(); - --i; - did_remove = true; - } - return did_remove; - }; - - if (swap_remove(m_notifiers)) { - // Make sure we aren't holding on to read versions needlessly if there - // are no notifiers left, but don't close them entirely as opening shared - // groups is expensive - if (m_notifiers.empty() && m_notifier_sg) { - REALM_ASSERT_3(m_notifier_sg->get_transact_stage(), ==, SharedGroup::transact_Reading); - m_notifier_sg->end_read(); - } - } - if (swap_remove(m_new_notifiers) && m_advancer_sg) { - REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading); - if (m_new_notifiers.empty()) { - m_advancer_sg->end_read(); - } - } -} - -void RealmCoordinator::on_change() -{ - run_async_notifiers(); - - std::lock_guard lock(m_realm_mutex); - for (auto& realm : m_weak_realm_notifiers) { - realm.notify(); - } -} - -namespace { -class IncrementalChangeInfo { -public: - IncrementalChangeInfo(SharedGroup& sg, - SchemaMode schema_mode, - std::vector>& notifiers) - : m_sg(sg), m_schema_mode(schema_mode) - { - if (notifiers.empty()) - return; - - auto cmp = [&](auto&& lft, auto&& rgt) { - return lft->version() < rgt->version(); - }; - - // Sort the notifiers by their source version so that we can pull them - // all forward to the latest version in a single pass over the transaction log - std::sort(notifiers.begin(), notifiers.end(), cmp); - - // Preallocate the required amount of space in the vector so that we can - // safely give out pointers to within the vector - size_t count = 1; - for (auto it = notifiers.begin(), next = it + 1; next != notifiers.end(); ++it, ++next) { - if (cmp(*it, *next)) - ++count; - } - m_info.reserve(count); - m_info.resize(1); - m_current = &m_info[0]; - } - - TransactionChangeInfo& current() const { return *m_current; } - - bool advance_incremental(VersionID version) - { - if (version != m_sg.get_version_of_current_transaction()) { - transaction::advance(m_sg, *m_current, version); - m_info.push_back({ - m_current->table_modifications_needed, - m_current->table_moves_needed, - std::move(m_current->lists)}); - m_current = &m_info.back(); - return true; - } - return false; - } - - void advance_to_final(VersionID version) - { - if (!m_current) { - transaction::advance(m_sg, nullptr, m_schema_mode, version); - return; - } - - transaction::advance(m_sg, *m_current, version); - - // We now need to combine the transaction change info objects so that all of - // the notifiers see the complete set of changes from their first version to - // the most recent one - for (size_t i = m_info.size() - 1; i > 0; --i) { - auto& cur = m_info[i]; - if (cur.tables.empty()) - continue; - auto& prev = m_info[i - 1]; - if (prev.tables.empty()) { - prev.tables = cur.tables; - continue; - } - - for (size_t j = 0; j < prev.tables.size() && j < cur.tables.size(); ++j) { - prev.tables[j].merge(CollectionChangeBuilder{cur.tables[j]}); - } - prev.tables.reserve(cur.tables.size()); - while (prev.tables.size() < cur.tables.size()) { - prev.tables.push_back(cur.tables[prev.tables.size()]); - } - } - - // Copy the list change info if there are multiple LinkViews for the same LinkList - auto id = [](auto const& list) { return std::tie(list.table_ndx, list.col_ndx, list.row_ndx); }; - for (size_t i = 1; i < m_current->lists.size(); ++i) { - for (size_t j = i; j > 0; --j) { - if (id(m_current->lists[i]) == id(m_current->lists[j - 1])) { - m_current->lists[j - 1].changes->merge(CollectionChangeBuilder{*m_current->lists[i].changes}); - } - } - } - } - -private: - std::vector m_info; - TransactionChangeInfo* m_current = nullptr; - SharedGroup& m_sg; - SchemaMode m_schema_mode; -}; -} // anonymous namespace - -void RealmCoordinator::run_async_notifiers() -{ - std::unique_lock lock(m_notifier_mutex); - - clean_up_dead_notifiers(); - - if (m_notifiers.empty() && m_new_notifiers.empty()) { - return; - } - - if (!m_async_error) { - open_helper_shared_group(); - } - - if (m_async_error) { - std::move(m_new_notifiers.begin(), m_new_notifiers.end(), std::back_inserter(m_notifiers)); - m_new_notifiers.clear(); - return; - } - - VersionID version; - - // Advance all of the new notifiers to the most recent version, if any - auto new_notifiers = std::move(m_new_notifiers); - IncrementalChangeInfo new_notifier_change_info(*m_advancer_sg, m_config.schema_mode, new_notifiers); - - if (!new_notifiers.empty()) { - REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading); - REALM_ASSERT_3(m_advancer_sg->get_version_of_current_transaction().version, - <=, new_notifiers.front()->version().version); - - // The advancer SG can be at an older version than the oldest new notifier - // if a notifier was added and then removed before it ever got the chance - // to run, as we don't move the pin forward when removing dead notifiers - transaction::advance(*m_advancer_sg, nullptr, m_config.schema_mode, new_notifiers.front()->version()); - - // Advance each of the new notifiers to the latest version, attaching them - // to the SG at their handover version. This requires a unique - // TransactionChangeInfo for each source version, so that things don't - // see changes from before the version they were handed over from. - // Each Info has all of the changes between that source version and the - // next source version, and they'll be merged together later after - // releasing the lock - for (auto& notifier : new_notifiers) { - new_notifier_change_info.advance_incremental(notifier->version()); - notifier->attach_to(*m_advancer_sg); - notifier->add_required_change_info(new_notifier_change_info.current()); - } - new_notifier_change_info.advance_to_final(VersionID{}); - - for (auto& notifier : new_notifiers) { - notifier->detach(); - } - version = m_advancer_sg->get_version_of_current_transaction(); - m_advancer_sg->end_read(); - } - REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Ready); - - auto skip_version = m_notifier_skip_version; - m_notifier_skip_version = {0, 0}; - - // Make a copy of the notifiers vector and then release the lock to avoid - // blocking other threads trying to register or unregister notifiers while we run them - auto notifiers = m_notifiers; - m_notifiers.insert(m_notifiers.end(), new_notifiers.begin(), new_notifiers.end()); - lock.unlock(); - - if (skip_version.version) { - REALM_ASSERT(version >= skip_version); - IncrementalChangeInfo change_info(*m_notifier_sg, m_config.schema_mode, notifiers); - for (auto& notifier : notifiers) - notifier->add_required_change_info(change_info.current()); - change_info.advance_to_final(skip_version); - - for (auto& notifier : notifiers) - notifier->run(); - - lock.lock(); - for (auto& notifier : notifiers) - notifier->prepare_handover(); - lock.unlock(); - } - - // Advance the non-new notifiers to the same version as we advanced the new - // ones to (or the latest if there were no new ones) - IncrementalChangeInfo change_info(*m_notifier_sg, m_config.schema_mode, notifiers); - for (auto& notifier : notifiers) { - notifier->add_required_change_info(change_info.current()); - } - change_info.advance_to_final(version); - - // Attach the new notifiers to the main SG and move them to the main list - for (auto& notifier : new_notifiers) { - notifier->attach_to(*m_notifier_sg); - notifier->run(); - } - - // Change info is now all ready, so the notifiers can now perform their - // background work - for (auto& notifier : notifiers) { - notifier->run(); - } - - // Reacquire the lock while updating the fields that are actually read on - // other threads - lock.lock(); - for (auto& notifier : new_notifiers) { - notifier->prepare_handover(); - } - for (auto& notifier : notifiers) { - notifier->prepare_handover(); - } - clean_up_dead_notifiers(); - m_notifier_cv.notify_all(); -} - -void RealmCoordinator::open_helper_shared_group() -{ - if (!m_notifier_sg) { - try { - std::unique_ptr read_only_group; - Realm::open_with_config(m_config, m_notifier_history, m_notifier_sg, read_only_group, nullptr); - REALM_ASSERT(!read_only_group); - m_notifier_sg->begin_read(); - } - catch (...) { - // Store the error to be passed to the async notifiers - m_async_error = std::current_exception(); - m_notifier_sg = nullptr; - m_notifier_history = nullptr; - } - } - else if (m_notifiers.empty()) { - m_notifier_sg->begin_read(); - } -} - -void RealmCoordinator::advance_to_ready(Realm& realm) -{ - std::unique_lock lock(m_notifier_mutex); - _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); - lock.unlock(); - notifiers.package_and_wait(util::none); - - auto& sg = Realm::Internal::get_shared_group(realm); - if (!notifiers) { - transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, VersionID{}); - return; - } - - auto version = notifiers.version(); - if (version && *version <= sg.get_version_of_current_transaction()) - return; - - transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); -} - -std::vector> RealmCoordinator::notifiers_for_realm(Realm& realm) -{ - std::vector> ret; - for (auto& notifier : m_new_notifiers) { - if (notifier->is_for_realm(realm)) - ret.push_back(notifier); - } - for (auto& notifier : m_notifiers) { - if (notifier->is_for_realm(realm)) - ret.push_back(notifier); - } - return ret; -} - -bool RealmCoordinator::advance_to_latest(Realm& realm) -{ - using sgf = SharedGroupFriend; - - auto& sg = Realm::Internal::get_shared_group(realm); - std::unique_lock lock(m_notifier_mutex); - _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); - lock.unlock(); - notifiers.package_and_wait(sgf::get_version_of_latest_snapshot(sg)); - - auto version = sg.get_version_of_current_transaction(); - transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); - return version != sg.get_version_of_current_transaction(); -} - -void RealmCoordinator::promote_to_write(Realm& realm) -{ - REALM_ASSERT(!realm.is_in_transaction()); - - std::unique_lock lock(m_notifier_mutex); - _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); - lock.unlock(); - - auto& sg = Realm::Internal::get_shared_group(realm); - transaction::begin(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); -} - -void RealmCoordinator::process_available_async(Realm& realm) -{ - REALM_ASSERT(!realm.is_in_transaction()); - - std::unique_lock lock(m_notifier_mutex); - auto notifiers = notifiers_for_realm(realm); - if (notifiers.empty()) - return; - - if (auto error = m_async_error) { - lock.unlock(); - for (auto& notifier : notifiers) - notifier->deliver_error(m_async_error); - return; - } - - bool in_read = realm.is_in_read_transaction(); - auto& sg = Realm::Internal::get_shared_group(realm); - auto version = sg.get_version_of_current_transaction(); - auto package = [&](auto& notifier) { - return !(notifier->has_run() && (!in_read || notifier->version() == version) && notifier->package_for_delivery()); - }; - notifiers.erase(std::remove_if(begin(notifiers), end(notifiers), package), end(notifiers)); - lock.unlock(); - - // no before advance because the Realm is already at the given version, - // because we're either sending initial notifications or the write was - // done on this Realm instance - - // Skip delivering if the Realm isn't in a read transaction - if (in_read) { - for (auto& notifier : notifiers) - notifier->deliver(sg); - } - - // but still call the change callbacks - for (auto& notifier : notifiers) - notifier->after_advance(); -} - -void RealmCoordinator::set_transaction_callback(std::function fn) -{ - m_transaction_callback = std::move(fn); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp deleted file mode 100644 index 28ab8d6..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp +++ /dev/null @@ -1,224 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/results_notifier.hpp" - -using namespace realm; -using namespace realm::_impl; - -ResultsNotifier::ResultsNotifier(Results& target) -: CollectionNotifier(target.get_realm()) -, m_target_results(&target) -, m_target_is_in_table_order(target.is_in_table_order()) -{ - Query q = target.get_query(); - set_table(*q.get_table()); - m_query_handover = Realm::Internal::get_shared_group(*get_realm()).export_for_handover(q, MutableSourcePayload::Move); - SortDescriptor::generate_patch(target.get_sort(), m_sort_handover); -} - -void ResultsNotifier::target_results_moved(Results& old_target, Results& new_target) -{ - auto lock = lock_target(); - - REALM_ASSERT(m_target_results == &old_target); - m_target_results = &new_target; -} - -void ResultsNotifier::release_data() noexcept -{ - m_query = nullptr; -} - -// Most of the inter-thread synchronization for run(), prepare_handover(), -// attach_to(), detach(), release_data() and deliver() is done by -// RealmCoordinator external to this code, which has some potentially -// non-obvious results on which members are and are not safe to use without -// holding a lock. -// -// add_required_change_info(), attach_to(), detach(), run(), -// prepare_handover(), and release_data() are all only ever called on a single -// background worker thread. call_callbacks() and deliver() are called on the -// target thread. Calls to prepare_handover() and deliver() are guarded by a -// lock. -// -// In total, this means that the safe data flow is as follows: -// - add_Required_change_info(), prepare_handover(), attach_to(), detach() and -// release_data() can read members written by each other -// - deliver() can read members written to in prepare_handover(), deliver(), -// and call_callbacks() -// - call_callbacks() and read members written to in deliver() -// -// Separately from the handover data flow, m_target_results is guarded by the target lock - -bool ResultsNotifier::do_add_required_change_info(TransactionChangeInfo& info) -{ - REALM_ASSERT(m_query); - m_info = &info; - - auto table_ndx = m_query->get_table()->get_index_in_group(); - if (info.table_moves_needed.size() <= table_ndx) - info.table_moves_needed.resize(table_ndx + 1); - info.table_moves_needed[table_ndx] = true; - - return has_run() && have_callbacks(); -} - -bool ResultsNotifier::need_to_run() -{ - REALM_ASSERT(m_info); - REALM_ASSERT(!m_tv.is_attached()); - - { - auto lock = lock_target(); - // Don't run the query if the results aren't actually going to be used - if (!get_realm() || (!have_callbacks() && !m_target_results->wants_background_updates())) { - return false; - } - } - - // If we've run previously, check if we need to rerun - if (has_run() && m_query->sync_view_if_needed() == m_last_seen_version) { - return false; - } - - return true; -} - -void ResultsNotifier::calculate_changes() -{ - size_t table_ndx = m_query->get_table()->get_index_in_group(); - if (has_run()) { - auto changes = table_ndx < m_info->tables.size() ? &m_info->tables[table_ndx] : nullptr; - - std::vector next_rows; - next_rows.reserve(m_tv.size()); - for (size_t i = 0; i < m_tv.size(); ++i) - next_rows.push_back(m_tv[i].get_index()); - - util::Optional move_candidates; - if (changes) { - auto const& moves = changes->moves; - for (auto& idx : m_previous_rows) { - auto it = lower_bound(begin(moves), end(moves), idx, - [](auto const& a, auto b) { return a.from < b; }); - if (it != moves.end() && it->from == idx) - idx = it->to; - else if (changes->deletions.contains(idx)) - idx = npos; - else - REALM_ASSERT_DEBUG(!changes->insertions.contains(idx)); - } - if (m_target_is_in_table_order && !m_sort) - move_candidates = changes->insertions; - } - - m_changes = CollectionChangeBuilder::calculate(m_previous_rows, next_rows, - get_modification_checker(*m_info, *m_query->get_table()), - move_candidates); - - m_previous_rows = std::move(next_rows); - } - else { - m_previous_rows.resize(m_tv.size()); - for (size_t i = 0; i < m_tv.size(); ++i) - m_previous_rows[i] = m_tv[i].get_index(); - } -} - -void ResultsNotifier::run() -{ - if (!need_to_run()) - return; - - m_query->sync_view_if_needed(); - m_tv = m_query->find_all(); - if (m_sort) { - m_tv.sort(m_sort); - } - m_last_seen_version = m_tv.sync_if_needed(); - - calculate_changes(); -} - -void ResultsNotifier::do_prepare_handover(SharedGroup& sg) -{ - if (!m_tv.is_attached()) { - // if the table version didn't change we can just reuse the same handover - // object and bump its version to the current SG version - if (m_tv_handover) - m_tv_handover->version = sg.get_version_of_current_transaction(); - return; - } - - REALM_ASSERT(m_tv.is_in_sync()); - - m_tv_handover = sg.export_for_handover(m_tv, MutableSourcePayload::Move); - - add_changes(std::move(m_changes)); - REALM_ASSERT(m_changes.empty()); - - // detach the TableView as we won't need it again and keeping it around - // makes advance_read() much more expensive - m_tv = {}; -} - -void ResultsNotifier::deliver(SharedGroup& sg) -{ - auto lock = lock_target(); - - // Target realm being null here indicates that we were unregistered while we - // were in the process of advancing the Realm version and preparing for - // delivery, i.e. the results was destroyed from the "wrong" thread - if (!get_realm()) { - return; - } - - REALM_ASSERT(!m_query_handover); - if (m_tv_to_deliver) { - Results::Internal::set_table_view(*m_target_results, - std::move(*sg.import_from_handover(std::move(m_tv_to_deliver)))); - } - REALM_ASSERT(!m_tv_to_deliver); -} - -bool ResultsNotifier::prepare_to_deliver() -{ - auto lock = lock_target(); - if (!get_realm()) - return false; - m_tv_to_deliver = std::move(m_tv_handover); - return true; -} - -void ResultsNotifier::do_attach_to(SharedGroup& sg) -{ - REALM_ASSERT(m_query_handover); - m_query = sg.import_from_handover(std::move(m_query_handover)); - m_sort = SortDescriptor::create_from_and_consume_patch(m_sort_handover, *m_query->get_table()); -} - -void ResultsNotifier::do_detach_from(SharedGroup& sg) -{ - REALM_ASSERT(m_query); - REALM_ASSERT(!m_tv.is_attached()); - - SortDescriptor::generate_patch(m_sort, m_sort_handover); - m_query_handover = sg.export_for_handover(*m_query, MutableSourcePayload::Move); - m_query = nullptr; -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp deleted file mode 100644 index 759b019..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp +++ /dev/null @@ -1,875 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/transact_log_handler.hpp" - -#include "binding_context.hpp" -#include "impl/collection_notifier.hpp" -#include "index_set.hpp" -#include "shared_realm.hpp" - -#include -#include - -#include - -using namespace realm; - -namespace { -template -struct MarkDirtyMixin { - bool mark_dirty(size_t row, size_t col, _impl::Instruction instr=_impl::instr_Set) - { - // Ignore SetDefault and SetUnique as those conceptually cannot be - // changes to existing rows - if (instr == _impl::instr_Set) - static_cast(this)->mark_dirty(row, col); - return true; - } - - bool set_int(size_t c, size_t r, int_fast64_t, _impl::Instruction i, size_t) { return mark_dirty(r, c, i); } - bool set_bool(size_t c, size_t r, bool, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_float(size_t c, size_t r, float, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_double(size_t c, size_t r, double, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_string(size_t c, size_t r, StringData, _impl::Instruction i, size_t) { return mark_dirty(r, c, i); } - bool set_binary(size_t c, size_t r, BinaryData, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_olddatetime(size_t c, size_t r, OldDateTime, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_timestamp(size_t c, size_t r, Timestamp, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_table(size_t c, size_t r, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_mixed(size_t c, size_t r, const Mixed&, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_link(size_t c, size_t r, size_t, size_t, _impl::Instruction i) { return mark_dirty(r, c, i); } - bool set_null(size_t c, size_t r, _impl::Instruction i, size_t) { return mark_dirty(r, c, i); } - - bool add_int(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); } - bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } - bool insert_substring(size_t col, size_t row, size_t, StringData) { return mark_dirty(row, col); } - bool erase_substring(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); } - - bool set_int_unique(size_t, size_t, size_t, int_fast64_t) { return true; } - bool set_string_unique(size_t, size_t, size_t, StringData) { return true; } -}; - -class TransactLogValidationMixin { - // Index of currently selected table - size_t m_current_table = 0; - - // Tables which were created during the transaction being processed, which - // can have columns inserted without a schema version bump - std::vector m_new_tables; - - REALM_NORETURN - REALM_NOINLINE - void schema_error() - { - throw std::logic_error("Schema mismatch detected: another process has modified the Realm file's schema in an incompatible way"); - } - - // Throw an exception if the currently modified table already existed before - // the current set of modifications - bool schema_error_unless_new_table() - { - if (schema_mode == SchemaMode::Additive) { - return true; - } - if (std::find(begin(m_new_tables), end(m_new_tables), m_current_table) != end(m_new_tables)) { - return true; - } - schema_error(); - } - -protected: - size_t current_table() const noexcept { return m_current_table; } - -public: - SchemaMode schema_mode; - - // Schema changes which don't involve a change in the schema version are - // allowed - bool add_search_index(size_t) { return true; } - bool remove_search_index(size_t) { return true; } - - // Creating entirely new tables without a schema version bump is allowed, so - // we need to track if new columns are being added to a new table or an - // existing one - bool insert_group_level_table(size_t table_ndx, size_t, StringData) - { - // Shift any previously added tables after the new one - for (auto& table : m_new_tables) { - if (table >= table_ndx) - ++table; - } - m_new_tables.push_back(table_ndx); - m_current_table = table_ndx; - return true; - } - bool insert_column(size_t, DataType, StringData, bool) { return schema_error_unless_new_table(); } - bool insert_link_column(size_t, DataType, StringData, size_t, size_t) { return schema_error_unless_new_table(); } - bool set_link_type(size_t, LinkType) { return schema_error_unless_new_table(); } - bool move_column(size_t, size_t) { return schema_error_unless_new_table(); } - bool move_group_level_table(size_t, size_t) { return schema_error_unless_new_table(); } - - // Removing or renaming things while a Realm is open is never supported - bool erase_group_level_table(size_t, size_t) { schema_error(); } - bool rename_group_level_table(size_t, StringData) { schema_error(); } - bool erase_column(size_t) { schema_error(); } - bool erase_link_column(size_t, size_t, size_t) { schema_error(); } - bool rename_column(size_t, StringData) { schema_error(); } - - bool select_descriptor(int levels, const size_t*) - { - // subtables not supported - return levels == 0; - } - - bool select_table(size_t group_level_ndx, int, const size_t*) noexcept - { - m_current_table = group_level_ndx; - return true; - } - - bool select_link_list(size_t, size_t, size_t) { return true; } - - // Non-schema changes are all allowed - void parse_complete() { } - bool insert_empty_rows(size_t, size_t, size_t, bool) { return true; } - bool erase_rows(size_t, size_t, size_t, bool) { return true; } - bool swap_rows(size_t, size_t) { return true; } - bool clear_table() noexcept { return true; } - bool link_list_set(size_t, size_t, size_t) { return true; } - bool link_list_insert(size_t, size_t, size_t) { return true; } - bool link_list_erase(size_t, size_t) { return true; } - bool link_list_nullify(size_t, size_t) { return true; } - bool link_list_clear(size_t) { return true; } - bool link_list_move(size_t, size_t) { return true; } - bool link_list_swap(size_t, size_t) { return true; } - bool merge_rows(size_t, size_t) { return true; } - bool optimize_table() { return true; } - -}; - - -// A transaction log handler that just validates that all operations made are -// ones supported by the object store -struct TransactLogValidator : public TransactLogValidationMixin, public MarkDirtyMixin { - TransactLogValidator(SchemaMode schema_mode) { this->schema_mode = schema_mode; } - void mark_dirty(size_t, size_t) { } -}; - -// Move the value at container[from] to container[to], shifting everything in -// between, or do nothing if either are out of bounds -template -void rotate(Container& container, size_t from, size_t to) -{ - REALM_ASSERT(from != to); - if (from >= container.size() && to >= container.size()) - return; - if (from >= container.size() || to >= container.size()) - container.resize(std::max(from, to) + 1); - if (from < to) - std::rotate(begin(container) + from, begin(container) + to, begin(container) + to + 1); - else - std::rotate(begin(container) + to, begin(container) + from, begin(container) + from + 1); -} - -// Insert a default-initialized value at pos if there is anything after pos in the container. -template -void insert_empty_at(Container& container, size_t pos) -{ - if (pos < container.size()) - container.insert(container.begin() + pos, typename Container::value_type{}); -} - -// Shift `value` to reflect a move from `from` to `to` -void adjust_for_move(size_t& value, size_t from, size_t to) -{ - if (value == from) - value = to; - else if (value > from && value < to) - --value; - else if (value < from && value >= to) - ++value; -} - -// Extends TransactLogValidator to also track changes and report it to the -// binding context if any properties are being observed -class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyMixin { - using ColumnInfo = BindingContext::ColumnInfo; - using ObserverState = BindingContext::ObserverState; - - // Observed table rows which need change information - std::vector m_observers; - // Userdata pointers for rows which have been deleted - std::vector invalidated; - // Delegate to send change information to - BindingContext* m_context; - - // Change information for the currently selected LinkList, if any - ColumnInfo* m_active_linklist = nullptr; - - _impl::NotifierPackage& m_notifiers; - SharedGroup& m_sg; - - // Get the change info for the given column, creating it if needed - static ColumnInfo& get_change(ObserverState& state, size_t i) - { - expand_to(state, i); - return state.changes[i]; - } - - static void expand_to(ObserverState& state, size_t i) - { - auto old_size = state.changes.size(); - if (old_size <= i) { - auto new_size = std::max(state.changes.size() * 2, i + 1); - state.changes.resize(new_size); - size_t base = old_size == 0 ? 0 : state.changes[old_size - 1].initial_column_index + 1; - for (size_t i = old_size; i < new_size; ++i) - state.changes[i].initial_column_index = i - old_size + base; - } - } - - // Remove the given observer from the list of observed objects and add it - // to the listed of invalidated objects - void invalidate(ObserverState *o) - { - invalidated.push_back(o->info); - m_observers.erase(m_observers.begin() + (o - &m_observers[0])); - } - -public: - template - TransactLogObserver(BindingContext* context, SharedGroup& sg, Func&& func, - util::Optional schema_mode, - _impl::NotifierPackage& notifiers) - : m_context(context) - , m_notifiers(notifiers) - , m_sg(sg) - { - auto old_version = sg.get_version_of_current_transaction(); - if (context) { - m_observers = context->get_observed_rows(); - } - - // If we have collection notifiers we have to use the transaction log - // observer to send will_change notifications once we know what the - // target version is, despite not otherwise needing to observe anything - if (m_observers.empty() && (!m_notifiers || m_notifiers.version())) { - m_notifiers.before_advance(); - if (schema_mode) { - func(TransactLogValidator(*schema_mode)); - } - else { - func(); - } - if (context && old_version != sg.get_version_of_current_transaction()) { - context->did_change({}, {}); - } - m_notifiers.deliver(sg); - m_notifiers.after_advance(); - return; - } - - std::sort(begin(m_observers), end(m_observers)); - func(*this); - if (context) - context->did_change(m_observers, invalidated, old_version != sg.get_version_of_current_transaction()); - m_notifiers.package_and_wait(sg.get_version_of_current_transaction().version); // is a no-op if parse_complete() was called - m_notifiers.deliver(sg); // only will ever deliver errors - m_notifiers.after_advance(); - } - - // Mark the given row/col as needing notifications sent - void mark_dirty(size_t row_ndx, size_t col_ndx) - { - auto it = lower_bound(begin(m_observers), end(m_observers), ObserverState{current_table(), row_ndx, nullptr}); - if (it != end(m_observers) && it->table_ndx == current_table() && it->row_ndx == row_ndx) { - get_change(*it, col_ndx).kind = ColumnInfo::Kind::Set; - } - } - - // Called at the end of the transaction log immediately before the version - // is advanced - void parse_complete() - { - if (m_context) - m_context->will_change(m_observers, invalidated); - using sgf = _impl::SharedGroupFriend; - m_notifiers.package_and_wait(sgf::get_version_of_latest_snapshot(m_sg)); - m_notifiers.before_advance(); - } - - bool insert_group_level_table(size_t table_ndx, size_t prior_size, StringData name) - { - for (auto& observer : m_observers) { - if (observer.table_ndx >= table_ndx) - ++observer.table_ndx; - } - TransactLogValidationMixin::insert_group_level_table(table_ndx, prior_size, name); - return true; - } - - bool insert_empty_rows(size_t row_ndx, size_t num_rows, size_t prior_size, bool) - { - if (row_ndx != prior_size) { - for (auto& observer : m_observers) { - if (observer.table_ndx == current_table() && observer.row_ndx >= row_ndx) - observer.row_ndx += num_rows; - } - } - return true; - } - - bool erase_rows(size_t row_ndx, size_t rows_to_erase, size_t prior_size, bool unordered) - { - REALM_ASSERT(unordered || rows_to_erase == 1); - size_t last_row_ndx = prior_size - 1; - - if (unordered) { - auto end = m_observers.end(); - auto row_it = lower_bound(begin(m_observers), end, ObserverState{current_table(), row_ndx, nullptr}); - auto last_it = lower_bound(row_it, end, ObserverState{current_table(), last_row_ndx, nullptr}); - bool have_row = row_it != end && row_it->table_ndx == current_table() && row_it->row_ndx == row_ndx; - bool have_last = last_it != end && last_it->table_ndx == current_table() && last_it->row_ndx == last_row_ndx; - if (have_row && have_last) { - invalidated.push_back(row_it->info); - row_it->info = last_it->info; - row_it->changes = std::move(last_it->changes); - m_observers.erase(last_it); - } - else if (have_row) { - invalidated.push_back(row_it->info); - m_observers.erase(row_it); - } - else if (have_last) { - last_it->row_ndx = row_ndx; - std::rotate(row_it, last_it, end); - } - } - else { - for (size_t i = 0; i < m_observers.size(); ++i) { - auto& o = m_observers[i]; - if (o.table_ndx == current_table()) { - if (o.row_ndx == row_ndx) { - invalidate(&o); - --i; - } - else if (o.row_ndx > row_ndx) { - o.row_ndx -= rows_to_erase; - } - } - } - } - return true; - } - - bool swap_rows(size_t row_ndx_1, size_t row_ndx_2) - { - REALM_ASSERT(row_ndx_1 < row_ndx_2); // this is enforced by core - - auto end = m_observers.end(); - auto it_1 = lower_bound(begin(m_observers), end, ObserverState{current_table(), row_ndx_1, nullptr}); - auto it_2 = lower_bound(it_1, end, ObserverState{current_table(), row_ndx_2, nullptr}); - bool have_row_1 = it_1 != end && it_1->table_ndx == current_table() && it_1->row_ndx == row_ndx_1; - bool have_row_2 = it_2 != end && it_2->table_ndx == current_table() && it_2->row_ndx == row_ndx_2; - - if (have_row_1 && have_row_2) { - std::swap(it_1->info, it_2->info); - std::swap(it_1->changes, it_2->changes); - } - else if (have_row_1) { - it_1->row_ndx = row_ndx_2; - std::rotate(it_1, it_1 + 1, it_2); - } - else if (have_row_2) { - it_2->row_ndx = row_ndx_1; - std::rotate(it_1, it_2, end); - } - - return true; - } - - bool merge_rows(size_t from, size_t to) - { - REALM_ASSERT(from != to); - - auto end = m_observers.end(); - auto from_it = lower_bound(begin(m_observers), end, ObserverState{current_table(), from, nullptr}); - if (from_it == end || from_it->table_ndx != current_table() || from_it->row_ndx != from) - return true; - - auto to_it = lower_bound(begin(m_observers), end, ObserverState{current_table(), to, nullptr}); - // an observer for the subsuming row should not already exist - REALM_ASSERT_DEBUG(to_it == end || (ObserverState{current_table(), to, nullptr}) < *to_it); - - from_it->row_ndx = to; - if (from < to) - std::rotate(from_it, from_it + 1, to_it); - else - std::rotate(to_it, from_it, from_it + 1); - return true; - } - - bool clear_table() - { - for (size_t i = 0; i < m_observers.size(); ) { - auto& o = m_observers[i]; - if (o.table_ndx == current_table()) { - invalidate(&o); - } - else { - ++i; - } - } - return true; - } - - bool select_link_list(size_t col, size_t row, size_t) - { - m_active_linklist = nullptr; - for (auto& o : m_observers) { - if (o.table_ndx == current_table() && o.row_ndx == row) { - m_active_linklist = &get_change(o, col); - break; - } - } - return true; - } - - void append_link_list_change(ColumnInfo::Kind kind, size_t index) { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - // Active LinkList isn't observed or already has multiple kinds of changes - return; - } - - if (o->kind == ColumnInfo::Kind::None) { - o->kind = kind; - o->indices.add(index); - } - else if (o->kind == kind) { - if (kind == ColumnInfo::Kind::Remove) { - o->indices.add_shifted(index); - } - else if (kind == ColumnInfo::Kind::Insert) { - o->indices.insert_at(index); - } - else { - o->indices.add(index); - } - } - else { - // Array KVO can only send a single kind of change at a time, so - // if there are multiple just give up and send "Set" - o->indices.set(0); - o->kind = ColumnInfo::Kind::SetAll; - } - } - - bool link_list_set(size_t index, size_t, size_t) - { - append_link_list_change(ColumnInfo::Kind::Set, index); - return true; - } - - bool link_list_insert(size_t index, size_t, size_t) - { - append_link_list_change(ColumnInfo::Kind::Insert, index); - return true; - } - - bool link_list_erase(size_t index, size_t) - { - append_link_list_change(ColumnInfo::Kind::Remove, index); - return true; - } - - bool link_list_nullify(size_t index, size_t) - { - append_link_list_change(ColumnInfo::Kind::Remove, index); - return true; - } - - bool link_list_swap(size_t index1, size_t index2) - { - append_link_list_change(ColumnInfo::Kind::Set, index1); - append_link_list_change(ColumnInfo::Kind::Set, index2); - return true; - } - - bool link_list_clear(size_t old_size) - { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - return true; - } - - if (o->kind == ColumnInfo::Kind::Remove) - old_size += o->indices.count(); - else if (o->kind == ColumnInfo::Kind::Insert) - old_size -= o->indices.count(); - - o->indices.set(old_size); - - o->kind = ColumnInfo::Kind::Remove; - return true; - } - - bool link_list_move(size_t from, size_t to) - { - ColumnInfo *o = m_active_linklist; - if (!o || o->kind == ColumnInfo::Kind::SetAll) { - return true; - } - if (from > to) { - std::swap(from, to); - } - - if (o->kind == ColumnInfo::Kind::None) { - o->kind = ColumnInfo::Kind::Set; - } - if (o->kind == ColumnInfo::Kind::Set) { - for (size_t i = from; i <= to; ++i) - o->indices.add(i); - } - else { - o->indices.set(0); - o->kind = ColumnInfo::Kind::SetAll; - } - return true; - } - - bool insert_column(size_t ndx, DataType, StringData, bool) - { - for (auto& observer : m_observers) { - if (observer.table_ndx == current_table()) { - expand_to(observer, ndx); - insert_empty_at(observer.changes, ndx); - } - } - return true; - } - - bool move_column(size_t from, size_t to) - { - for (auto& observer : m_observers) { - if (observer.table_ndx == current_table()) { - // have to initialize the columns one past the moved one so that - // we can later initialize any more columns after that - expand_to(observer, std::max(from, to) + 1); - rotate(observer.changes, from, to); - } - } - return true; - } - - bool move_group_level_table(size_t from, size_t to) - { - for (auto& observer : m_observers) - adjust_for_move(observer.table_ndx, from, to); - return true; - } - - bool insert_link_column(size_t ndx, DataType type, StringData name, size_t, size_t) { return insert_column(ndx, type, name, false); } - -}; - -// Extends TransactLogValidator to track changes made to LinkViews -class LinkViewObserver : public TransactLogValidationMixin, public MarkDirtyMixin { - _impl::TransactionChangeInfo& m_info; - _impl::CollectionChangeBuilder* m_active = nullptr; - - _impl::CollectionChangeBuilder* get_change() - { - auto tbl_ndx = current_table(); - if (!m_info.track_all && (tbl_ndx >= m_info.table_modifications_needed.size() || !m_info.table_modifications_needed[tbl_ndx])) - return nullptr; - if (m_info.tables.size() <= tbl_ndx) { - m_info.tables.resize(std::max(m_info.tables.size() * 2, tbl_ndx + 1)); - } - return &m_info.tables[tbl_ndx]; - } - - bool need_move_info() const - { - auto tbl_ndx = current_table(); - return m_info.track_all || (tbl_ndx < m_info.table_moves_needed.size() && m_info.table_moves_needed[tbl_ndx]); - } - -public: - LinkViewObserver(_impl::TransactionChangeInfo& info) - : m_info(info) { } - - void mark_dirty(size_t row, size_t) - { - if (auto change = get_change()) - change->modify(row); - } - - void parse_complete() - { - for (auto& table : m_info.tables) { - table.parse_complete(); - } - for (auto& list : m_info.lists) { - list.changes->clean_up_stale_moves(); - } - } - - bool select_link_list(size_t col, size_t row, size_t) - { - mark_dirty(row, col); - - m_active = nullptr; - // When there are multiple source versions there could be multiple - // change objects for a single LinkView, in which case we need to use - // the last one - for (auto it = m_info.lists.rbegin(), end = m_info.lists.rend(); it != end; ++it) { - if (it->table_ndx == current_table() && it->row_ndx == row && it->col_ndx == col) { - m_active = it->changes; - break; - } - } - return true; - } - - bool link_list_set(size_t index, size_t, size_t) - { - if (m_active) - m_active->modify(index); - return true; - } - - bool link_list_insert(size_t index, size_t, size_t) - { - if (m_active) - m_active->insert(index); - return true; - } - - bool link_list_erase(size_t index, size_t) - { - if (m_active) - m_active->erase(index); - return true; - } - - bool link_list_nullify(size_t index, size_t prior_size) - { - return link_list_erase(index, prior_size); - } - - bool link_list_swap(size_t index1, size_t index2) - { - link_list_set(index1, 0, npos); - link_list_set(index2, 0, npos); - return true; - } - - bool link_list_clear(size_t old_size) - { - if (m_active) - m_active->clear(old_size); - return true; - } - - bool link_list_move(size_t from, size_t to) - { - if (m_active) - m_active->move(from, to); - return true; - } - - bool insert_empty_rows(size_t row_ndx, size_t num_rows_to_insert, size_t, bool unordered) - { - REALM_ASSERT(!unordered); - if (auto change = get_change()) - change->insert(row_ndx, num_rows_to_insert, need_move_info()); - for (auto& list : m_info.lists) { - if (list.table_ndx == current_table() && list.row_ndx >= row_ndx) - list.row_ndx += num_rows_to_insert; - } - - return true; - } - - bool erase_rows(size_t row_ndx, size_t, size_t prior_num_rows, bool unordered) - { - REALM_ASSERT(unordered); - size_t last_row = prior_num_rows - 1; - - for (auto it = begin(m_info.lists); it != end(m_info.lists); ) { - if (it->table_ndx == current_table()) { - if (it->row_ndx == row_ndx) { - *it = std::move(m_info.lists.back()); - m_info.lists.pop_back(); - continue; - } - if (it->row_ndx == last_row) - it->row_ndx = row_ndx; - } - ++it; - } - - if (auto change = get_change()) - change->move_over(row_ndx, last_row, need_move_info()); - return true; - } - - bool swap_rows(size_t row_ndx_1, size_t row_ndx_2) { - REALM_ASSERT(row_ndx_1 < row_ndx_2); - for (auto& list : m_info.lists) { - if (list.table_ndx == current_table()) { - if (list.row_ndx == row_ndx_1) - list.row_ndx = row_ndx_2; - else if (list.row_ndx == row_ndx_2) - list.row_ndx = row_ndx_1; - } - } - if (auto change = get_change()) - change->swap(row_ndx_1, row_ndx_2, need_move_info()); - return true; - } - - bool merge_rows(size_t from, size_t to) - { - for (auto& list : m_info.lists) { - if (list.table_ndx == current_table() && list.row_ndx == from) - list.row_ndx = to; - } - if (auto change = get_change()) - change->subsume(from, to, need_move_info()); - return true; - } - - bool clear_table() - { - auto tbl_ndx = current_table(); - auto it = remove_if(begin(m_info.lists), end(m_info.lists), - [&](auto const& lv) { return lv.table_ndx == tbl_ndx; }); - m_info.lists.erase(it, end(m_info.lists)); - if (auto change = get_change()) - change->clear(std::numeric_limits::max()); - return true; - } - - bool insert_column(size_t ndx, DataType, StringData, bool) - { - for (auto& list : m_info.lists) { - if (list.table_ndx == current_table() && list.col_ndx >= ndx) - ++list.col_ndx; - } - return true; - } - - bool insert_group_level_table(size_t ndx, size_t, StringData) - { - for (auto& list : m_info.lists) { - if (list.table_ndx >= ndx) - ++list.table_ndx; - } - insert_empty_at(m_info.tables, ndx); - insert_empty_at(m_info.table_moves_needed, ndx); - insert_empty_at(m_info.table_modifications_needed, ndx); - return true; - } - - bool move_column(size_t from, size_t to) - { - for (auto& list : m_info.lists) { - if (list.table_ndx == current_table()) - adjust_for_move(list.col_ndx, from, to); - } - return true; - } - - bool move_group_level_table(size_t from, size_t to) - { - for (auto& list : m_info.lists) - adjust_for_move(list.table_ndx, from, to); - rotate(m_info.tables, from, to); - rotate(m_info.table_modifications_needed, from, to); - rotate(m_info.table_moves_needed, from, to); - return true; - } - - bool insert_link_column(size_t ndx, DataType type, StringData name, size_t, size_t) { return insert_column(ndx, type, name, false); } - -}; -} // anonymous namespace - -namespace realm { -namespace _impl { - -namespace transaction { -void advance(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, VersionID version) -{ - _impl::NotifierPackage notifiers; - TransactLogObserver(context, sg, [&](auto&&... args) { - LangBindHelper::advance_read(sg, std::move(args)..., version); - }, schema_mode, notifiers); -} - -void advance(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, NotifierPackage& notifiers) -{ - TransactLogObserver(context, sg, [&](auto&&... args) { - LangBindHelper::advance_read(sg, std::move(args)..., notifiers.version().value_or(VersionID{})); - }, schema_mode, notifiers); -} - -void begin_without_validation(SharedGroup& sg) -{ - LangBindHelper::promote_to_write(sg); -} - -void begin(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, - NotifierPackage& notifiers) -{ - TransactLogObserver(context, sg, [&](auto&&... args) { - LangBindHelper::promote_to_write(sg, std::move(args)...); - }, schema_mode, notifiers); -} - -void commit(SharedGroup& sg) -{ - LangBindHelper::commit_and_continue_as_read(sg); -} - -void cancel(SharedGroup& sg, BindingContext* context) -{ - _impl::NotifierPackage notifiers; - TransactLogObserver(context, sg, [&](auto&&... args) { - LangBindHelper::rollback_and_continue_as_read(sg, std::move(args)...); - }, util::none, notifiers); -} - -void advance(SharedGroup& sg, - TransactionChangeInfo& info, - VersionID version) -{ - if (!info.track_all && info.table_modifications_needed.empty() && info.lists.empty()) { - LangBindHelper::advance_read(sg, version); - } - else { - LangBindHelper::advance_read(sg, LinkViewObserver(info), version); - } - -} - -} // namespace transaction -} // namespace _impl -} // namespace realm diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/impl/weak_realm_notifier.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/impl/weak_realm_notifier.cpp deleted file mode 100644 index d181667..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/impl/weak_realm_notifier.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "impl/weak_realm_notifier.hpp" - -#include "shared_realm.hpp" -#include "util/event_loop_signal.hpp" - -using namespace realm; -using namespace realm::_impl; - -WeakRealmNotifier::WeakRealmNotifier(const std::shared_ptr& realm, bool cache) -: m_realm(realm) -, m_realm_key(realm.get()) -, m_cache(cache) -, m_signal(std::make_shared>(Callback{realm})) -{ -} - -WeakRealmNotifier::~WeakRealmNotifier() = default; - -void WeakRealmNotifier::Callback::operator()() -{ - if (auto realm = weak_realm.lock()) { - realm->notify(); - } -} - -void WeakRealmNotifier::notify() -{ - m_signal->notify(); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/index_set.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/index_set.cpp deleted file mode 100644 index a5c30c2..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/index_set.cpp +++ /dev/null @@ -1,707 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "index_set.hpp" - -#include - -#include - -using namespace realm; -using namespace realm::_impl; - -const size_t IndexSet::npos; - -template -void MutableChunkedRangeVectorIterator::set(size_t front, size_t back) -{ - this->m_outer->count -= this->m_inner->second - this->m_inner->first; - if (this->offset() == 0) { - this->m_outer->begin = front; - } - if (this->m_inner == &this->m_outer->data.back()) { - this->m_outer->end = back; - } - this->m_outer->count += back - front; - this->m_inner->first = front; - this->m_inner->second = back; -} - -template -void MutableChunkedRangeVectorIterator::adjust(ptrdiff_t front, ptrdiff_t back) -{ - if (this->offset() == 0) { - this->m_outer->begin += front; - } - if (this->m_inner == &this->m_outer->data.back()) { - this->m_outer->end += back; - } - this->m_outer->count += -front + back; - this->m_inner->first += front; - this->m_inner->second += back; -} - -template -void MutableChunkedRangeVectorIterator::shift(ptrdiff_t distance) -{ - if (this->offset() == 0) { - this->m_outer->begin += distance; - } - if (this->m_inner == &this->m_outer->data.back()) { - this->m_outer->end += distance; - } - this->m_inner->first += distance; - this->m_inner->second += distance; -} - -void ChunkedRangeVector::push_back(value_type value) -{ - if (!empty() && m_data.back().data.size() < max_size) { - auto& range = m_data.back(); - REALM_ASSERT(range.end <= value.first); - - range.data.push_back(value); - range.count += value.second - value.first; - range.end = value.second; - } - else { - m_data.push_back({{std::move(value)}, value.first, value.second, value.second - value.first}); - } - verify(); -} - -ChunkedRangeVector::iterator ChunkedRangeVector::insert(iterator pos, value_type value) -{ - if (pos.m_outer == m_data.end()) { - push_back(std::move(value)); - return std::prev(end()); - } - - pos = ensure_space(pos); - auto& chunk = *pos.m_outer; - pos.m_inner = &*chunk.data.insert(pos.m_outer->data.begin() + pos.offset(), value); - chunk.count += value.second - value.first; - chunk.begin = std::min(chunk.begin, value.first); - chunk.end = std::max(chunk.end, value.second); - - verify(); - return pos; -} - -ChunkedRangeVector::iterator ChunkedRangeVector::ensure_space(iterator pos) -{ - if (pos.m_outer->data.size() + 1 <= max_size) - return pos; - - auto offset = pos.offset(); - - // Split the chunk in half to make space for the new insertion - auto new_pos = m_data.insert(pos.m_outer + 1, Chunk{}); - auto prev = new_pos - 1; - auto to_move = max_size / 2; - new_pos->data.reserve(to_move); - new_pos->data.assign(prev->data.end() - to_move, prev->data.end()); - prev->data.resize(prev->data.size() - to_move); - - size_t moved_count = 0; - for (auto range : new_pos->data) - moved_count += range.second - range.first; - - prev->end = prev->data.back().second; - prev->count -= moved_count; - new_pos->begin = new_pos->data.front().first; - new_pos->end = new_pos->data.back().second; - new_pos->count = moved_count; - - if (offset >= to_move) { - pos.m_outer = new_pos; - offset -= to_move; - } - else { - pos.m_outer = prev; - } - pos.m_end = m_data.end(); - pos.m_inner = &pos.m_outer->data[offset]; - verify(); - return pos; -} - -ChunkedRangeVector::iterator ChunkedRangeVector::erase(iterator pos) -{ - auto offset = pos.offset(); - auto& chunk = *pos.m_outer; - chunk.count -= pos->second - pos->first; - chunk.data.erase(chunk.data.begin() + offset); - - if (chunk.data.size() == 0) { - pos.m_outer = m_data.erase(pos.m_outer); - pos.m_end = m_data.end(); - pos.m_inner = pos.m_outer == m_data.end() ? nullptr : &pos.m_outer->data.front(); - verify(); - return pos; - } - - chunk.begin = chunk.data.front().first; - chunk.end = chunk.data.back().second; - if (offset < chunk.data.size()) - pos.m_inner = &chunk.data[offset]; - else { - ++pos.m_outer; - pos.m_inner = pos.m_outer == pos.m_end ? nullptr : &pos.m_outer->data.front(); - } - - verify(); - return pos; -} - -void ChunkedRangeVector::verify() const noexcept -{ -#ifdef REALM_DEBUG - size_t prev_end = -1; - for (auto range : *this) { - REALM_ASSERT(range.first < range.second); - REALM_ASSERT(prev_end == size_t(-1) || range.first > prev_end); - prev_end = range.second; - } - - for (auto& chunk : m_data) { - REALM_ASSERT(!chunk.data.empty()); - REALM_ASSERT(chunk.data.front().first == chunk.begin); - REALM_ASSERT(chunk.data.back().second == chunk.end); - REALM_ASSERT(chunk.count <= chunk.end - chunk.begin); - size_t count = 0; - for (auto range : chunk.data) - count += range.second - range.first; - REALM_ASSERT(count == chunk.count); - } -#endif -} - -namespace { -class ChunkedRangeVectorBuilder { -public: - using value_type = std::pair; - - ChunkedRangeVectorBuilder(ChunkedRangeVector const& expected); - void push_back(size_t index); - void push_back(std::pair range); - std::vector finalize(); -private: - std::vector m_data; - size_t m_outer_pos = 0; -}; - -ChunkedRangeVectorBuilder::ChunkedRangeVectorBuilder(ChunkedRangeVector const& expected) -{ - size_t size = 0; - for (auto const& chunk : expected.m_data) - size += chunk.data.size(); - m_data.resize(size / ChunkedRangeVector::max_size + 1); - for (size_t i = 0; i < m_data.size() - 1; ++i) - m_data[i].data.reserve(ChunkedRangeVector::max_size); -} - -void ChunkedRangeVectorBuilder::push_back(size_t index) -{ - push_back({index, index + 1}); -} - -void ChunkedRangeVectorBuilder::push_back(std::pair range) -{ - auto& chunk = m_data[m_outer_pos]; - if (chunk.data.empty()) { - chunk.data.push_back(range); - chunk.count = range.second - range.first; - chunk.begin = range.first; - } - else if (range.first == chunk.data.back().second) { - chunk.data.back().second = range.second; - chunk.count += range.second - range.first; - } - else if (chunk.data.size() < ChunkedRangeVector::max_size) { - chunk.data.push_back(range); - chunk.count += range.second - range.first; - } - else { - chunk.end = chunk.data.back().second; - ++m_outer_pos; - if (m_outer_pos >= m_data.size()) - m_data.push_back({{range}, range.first, 0, 1}); - else { - auto& chunk = m_data[m_outer_pos]; - chunk.data.push_back(range); - chunk.begin = range.first; - chunk.count = range.second - range.first; - } - } -} - -std::vector ChunkedRangeVectorBuilder::finalize() -{ - if (!m_data.empty()) { - m_data.resize(m_outer_pos + 1); - if (m_data.back().data.empty()) - m_data.pop_back(); - else - m_data.back().end = m_data.back().data.back().second; - } - return std::move(m_data); -} -} - -IndexSet::IndexSet(std::initializer_list values) -{ - for (size_t v : values) - add(v); -} - -bool IndexSet::contains(size_t index) const -{ - auto it = const_cast(this)->find(index); - return it != end() && it->first <= index; -} - -size_t IndexSet::count(size_t start_index, size_t end_index) const -{ - auto it = const_cast(this)->find(start_index); - const auto end = this->end(); - if (it == end || it->first >= end_index) { - return 0; - } - if (it->second >= end_index) - return std::min(it->second, end_index) - std::max(it->first, start_index); - - size_t ret = 0; - - if (start_index > it->first || it.offset() != 0) { - // Start index is in the middle of a chunk, so start by counting the - // rest of that chunk - ret = it->second - std::max(it->first, start_index); - for (++it; it != end && it->second < end_index && it.offset() != 0; ++it) { - ret += it->second - it->first; - } - if (it != end && it->first < end_index && it.offset() != 0) - ret += end_index - it->first; - if (it == end || it->second >= end_index) - return ret; - } - - // Now count all complete chunks that fall within the range - while (it != end && it.outer()->end <= end_index) { - REALM_ASSERT_DEBUG(it.offset() == 0); - ret += it.outer()->count; - it.next_chunk(); - } - - // Cound all complete ranges within the last chunk - while (it != end && it->second <= end_index) { - ret += it->second - it->first; - ++it; - } - - // And finally add in the partial last range - if (it != end && it->first < end_index) - ret += end_index - it->first; - return ret; -} - -IndexSet::iterator IndexSet::find(size_t index) -{ - return find(index, begin()); -} - -IndexSet::iterator IndexSet::find(size_t index, iterator begin) -{ - auto it = std::find_if(begin.outer(), m_data.end(), - [&](auto const& lft) { return lft.end > index; }); - if (it == m_data.end()) - return end(); - if (index < it->begin) - return iterator(it, m_data.end(), &it->data[0]); - auto inner_begin = it->data.begin(); - if (it == begin.outer()) - inner_begin += begin.offset(); - auto inner = std::lower_bound(inner_begin, it->data.end(), index, - [&](auto const& lft, auto) { return lft.second <= index; }); - REALM_ASSERT_DEBUG(inner != it->data.end()); - - return iterator(it, m_data.end(), &*inner); -} - -void IndexSet::add(size_t index) -{ - do_add(find(index), index); -} - -void IndexSet::add(IndexSet const& other) -{ - auto it = begin(); - for (size_t index : other.as_indexes()) { - it = do_add(find(index, it), index); - } -} - -size_t IndexSet::add_shifted(size_t index) -{ - iterator it = begin(), end = this->end(); - - // Shift for any complete chunks before the target - for (; it != end && it.outer()->end <= index; it.next_chunk()) - index += it.outer()->count; - - // And any ranges within the last partial chunk - for (; it != end && it->first <= index; ++it) - index += it->second - it->first; - - do_add(it, index); - return index; -} - -void IndexSet::add_shifted_by(IndexSet const& shifted_by, IndexSet const& values) -{ - if (values.empty()) - return; - -#ifdef REALM_DEBUG - size_t expected = std::distance(as_indexes().begin(), as_indexes().end()); - for (auto index : values.as_indexes()) { - if (!shifted_by.contains(index)) - ++expected; - } -#endif - - ChunkedRangeVectorBuilder builder(*this); - - auto old_it = cbegin(), old_end = cend(); - auto shift_it = shifted_by.cbegin(), shift_end = shifted_by.cend(); - - size_t skip_until = 0; - size_t old_shift = 0; - size_t new_shift = 0; - for (size_t index : values.as_indexes()) { - for (; shift_it != shift_end && shift_it->first <= index; ++shift_it) { - new_shift += shift_it->second - shift_it->first; - skip_until = shift_it->second; - } - if (index < skip_until) - continue; - - for (; old_it != old_end && old_it->first <= index - new_shift + old_shift; ++old_it) { - for (size_t i = old_it->first; i < old_it->second; ++i) - builder.push_back(i); - old_shift += old_it->second - old_it->first; - } - - REALM_ASSERT(index >= new_shift); - builder.push_back(index - new_shift + old_shift); - } - - copy(old_it, old_end, std::back_inserter(builder)); - m_data = builder.finalize(); - -#ifdef REALM_DEBUG - REALM_ASSERT((size_t)std::distance(as_indexes().begin(), as_indexes().end()) == expected); -#endif -} - -void IndexSet::set(size_t len) -{ - clear(); - if (len) { - push_back({0, len}); - } -} - -void IndexSet::insert_at(size_t index, size_t count) -{ - REALM_ASSERT(count > 0); - - auto pos = find(index); - auto end = this->end(); - bool in_existing = false; - if (pos != end) { - if (pos->first <= index) { - in_existing = true; - pos.adjust(0, count); - } - else { - pos.shift(count); - } - for (auto it = std::next(pos); it != end; ++it) - it.shift(count); - } - if (!in_existing) { - for (size_t i = 0; i < count; ++i) - pos = std::next(do_add(pos, index + i)); - } - - verify(); -} - -void IndexSet::insert_at(IndexSet const& positions) -{ - if (positions.empty()) - return; - if (empty()) { - *this = positions; - return; - } - - IndexIterator begin1 = cbegin(), begin2 = positions.cbegin(); - IndexIterator end1 = cend(), end2 = positions.cend(); - - ChunkedRangeVectorBuilder builder(*this); - size_t shift = 0; - while (begin1 != end1 && begin2 != end2) { - if (*begin1 + shift < *begin2) { - builder.push_back(*begin1++ + shift); - } - else { - ++shift; - builder.push_back(*begin2++); - } - } - for (; begin1 != end1; ++begin1) - builder.push_back(*begin1 + shift); - for (; begin2 != end2; ++begin2) - builder.push_back(*begin2); - - m_data = builder.finalize(); -} - -void IndexSet::shift_for_insert_at(size_t index, size_t count) -{ - REALM_ASSERT(count > 0); - - auto it = find(index); - if (it == end()) - return; - - for (auto pos = it, end = this->end(); pos != end; ++pos) - pos.shift(count); - - // If the range contained the insertion point, split the range and move - // the part of it before the insertion point back - if (it->first < index + count) { - auto old_second = it->second; - it.set(it->first - count, index); - insert(std::next(it), {index + count, old_second}); - } - verify(); -} - -void IndexSet::shift_for_insert_at(realm::IndexSet const& values) -{ - if (empty() || values.empty()) - return; - if (values.m_data.front().begin >= m_data.back().end) - return; - - IndexIterator begin1 = cbegin(), begin2 = values.cbegin(); - IndexIterator end1 = cend(), end2 = values.cend(); - - ChunkedRangeVectorBuilder builder(*this); - size_t shift = 0; - while (begin1 != end1 && begin2 != end2) { - if (*begin1 + shift < *begin2) { - builder.push_back(*begin1++ + shift); - } - else { - ++shift; - begin2++; - } - } - for (; begin1 != end1; ++begin1) - builder.push_back(*begin1 + shift); - - m_data = builder.finalize(); -} - -void IndexSet::erase_at(size_t index) -{ - auto it = find(index); - if (it != end()) - do_erase(it, index); -} - -void IndexSet::erase_at(IndexSet const& positions) -{ - if (empty() || positions.empty()) - return; - - ChunkedRangeVectorBuilder builder(*this); - - IndexIterator begin1 = cbegin(), begin2 = positions.cbegin(); - IndexIterator end1 = cend(), end2 = positions.cend(); - - size_t shift = 0; - while (begin1 != end1 && begin2 != end2) { - if (*begin1 < *begin2) { - builder.push_back(*begin1++ - shift); - } - else if (*begin1 == *begin2) { - ++shift; - ++begin1; - ++begin2; - } - else { - ++shift; - ++begin2; - } - } - for (; begin1 != end1; ++begin1) - builder.push_back(*begin1 - shift); - - m_data = builder.finalize(); -} - -size_t IndexSet::erase_or_unshift(size_t index) -{ - auto shifted = index; - iterator it = begin(), end = this->end(); - - // Shift for any complete chunks before the target - for (; it != end && it.outer()->end <= index; it.next_chunk()) - shifted -= it.outer()->count; - - // And any ranges within the last partial chunk - for (; it != end && it->second <= index; ++it) - shifted -= it->second - it->first; - - if (it == end) - return shifted; - - if (it->first <= index) - shifted = npos; - - do_erase(it, index); - - return shifted; -} - -void IndexSet::do_erase(iterator it, size_t index) -{ - if (it->first <= index) { - if (it->first + 1 == it->second) { - it = erase(it); - } - else { - it.adjust(0, -1); - ++it; - } - } - else if (it != begin() && std::prev(it)->second + 1 == it->first) { - std::prev(it).adjust(0, it->second - it->first); - it = erase(it); - } - - for (; it != end(); ++it) - it.shift(-1); -} - -IndexSet::iterator IndexSet::do_remove(iterator it, size_t begin, size_t end) -{ - for (it = find(begin, it); it != this->end() && it->first < end; it = find(begin, it)) { - // Trim off any part of the range to remove that's before the matching range - begin = std::max(it->first, begin); - - // If the matching range extends to both sides of the range to remove, - // split it on the range to remove - if (it->first < begin && it->second > end) { - auto old_second = it->second; - it.set(it->first, begin); - it = std::prev(insert(std::next(it), {end, old_second})); - } - // Range to delete now coverages (at least) one end of the matching range - else if (begin == it->first && end >= it->second) - it = erase(it); - else if (begin == it->first) - it.set(end, it->second); - else - it.set(it->first, begin); - } - return it; -} - -void IndexSet::remove(size_t index, size_t count) -{ - do_remove(find(index), index, index + count); -} - -void IndexSet::remove(realm::IndexSet const& values) -{ - auto it = begin(); - for (auto range : values) { - it = do_remove(it, range.first, range.second); - if (it == end()) - return; - } -} - -size_t IndexSet::shift(size_t index) const -{ - // FIXME: optimize - for (auto range : *this) { - if (range.first > index) - break; - index += range.second - range.first; - } - return index; -} - -size_t IndexSet::unshift(size_t index) const -{ - REALM_ASSERT_DEBUG(!contains(index)); - return index - count(0, index); -} - -void IndexSet::clear() -{ - m_data.clear(); -} - -IndexSet::iterator IndexSet::do_add(iterator it, size_t index) -{ - verify(); - bool more_before = it != begin(), valid = it != end(); - REALM_ASSERT(!more_before || index >= std::prev(it)->second); - if (valid && it->first <= index && it->second > index) { - // index is already in set - return it; - } - if (more_before && std::prev(it)->second == index) { - auto prev = std::prev(it); - // index is immediately after an existing range - prev.adjust(0, 1); - - if (valid && prev->second == it->first) { - // index joins two existing ranges - prev.adjust(0, it->second - it->first); - return std::prev(erase(it)); - } - return prev; - } - if (valid && it->first == index + 1) { - // index is immediately before an existing range - it.adjust(-1, 0); - return it; - } - - // index is not next to an existing range - return insert(it, {index, index + 1}); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/list.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/list.cpp deleted file mode 100644 index 4bab43a..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/list.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "list.hpp" - -#include "impl/list_notifier.hpp" -#include "impl/realm_coordinator.hpp" -#include "object_store.hpp" -#include "results.hpp" -#include "schema.hpp" -#include "shared_realm.hpp" -#include "util/format.hpp" - -#include - -using namespace realm; -using namespace realm::_impl; - -List::List() noexcept = default; -List::~List() = default; - -List::List(const List&) = default; -List& List::operator=(const List&) = default; -List::List(List&&) = default; -List& List::operator=(List&&) = default; - -List::List(std::shared_ptr r, LinkViewRef l) noexcept -: m_realm(std::move(r)) -, m_link_view(std::move(l)) -{ -} - -const ObjectSchema& List::get_object_schema() const -{ - verify_attached(); - - if (!m_object_schema) { - auto object_type = ObjectStore::object_type_for_table_name(m_link_view->get_target_table().get_name()); - auto it = m_realm->schema().find(object_type); - REALM_ASSERT(it != m_realm->schema().end()); - m_object_schema = &*it; - } - return *m_object_schema; -} - -Query List::get_query() const -{ - verify_attached(); - return m_link_view->get_target_table().where(m_link_view); -} - -size_t List::get_origin_row_index() const -{ - verify_attached(); - return m_link_view->get_origin_row_index(); -} - -void List::verify_valid_row(size_t row_ndx, bool insertion) const -{ - size_t size = m_link_view->size(); - if (row_ndx > size || (!insertion && row_ndx == size)) { - throw OutOfBoundsIndexException{row_ndx, size + insertion}; - } -} - -bool List::is_valid() const -{ - m_realm->verify_thread(); - return m_link_view && m_link_view->is_attached(); -} - -void List::verify_attached() const -{ - if (!is_valid()) { - throw InvalidatedException(); - } -} - -void List::verify_in_transaction() const -{ - verify_attached(); - if (!m_realm->is_in_transaction()) { - throw InvalidTransactionException("Must be in a write transaction"); - } -} - -size_t List::size() const -{ - verify_attached(); - return m_link_view->size(); -} - -RowExpr List::get(size_t row_ndx) const -{ - verify_attached(); - verify_valid_row(row_ndx); - return m_link_view->get(row_ndx); -} - -size_t List::get_unchecked(size_t row_ndx) const noexcept -{ - return m_link_view->get(row_ndx).get_index(); -} - -size_t List::find(ConstRow const& row) const -{ - verify_attached(); - - if (!row.is_attached() || row.get_table() != &m_link_view->get_target_table()) { - return not_found; - } - - return m_link_view->find(row.get_index()); -} - -void List::add(size_t target_row_ndx) -{ - verify_in_transaction(); - m_link_view->add(target_row_ndx); -} - -void List::insert(size_t row_ndx, size_t target_row_ndx) -{ - verify_in_transaction(); - verify_valid_row(row_ndx, true); - m_link_view->insert(row_ndx, target_row_ndx); -} - -void List::move(size_t source_ndx, size_t dest_ndx) -{ - verify_in_transaction(); - verify_valid_row(source_ndx); - verify_valid_row(dest_ndx); // Can't be one past end due to removing one earlier - m_link_view->move(source_ndx, dest_ndx); -} - -void List::remove(size_t row_ndx) -{ - verify_in_transaction(); - verify_valid_row(row_ndx); - m_link_view->remove(row_ndx); -} - -void List::remove_all() -{ - verify_in_transaction(); - m_link_view->clear(); -} - -void List::set(size_t row_ndx, size_t target_row_ndx) -{ - verify_in_transaction(); - verify_valid_row(row_ndx); - m_link_view->set(row_ndx, target_row_ndx); -} - -void List::swap(size_t ndx1, size_t ndx2) -{ - verify_in_transaction(); - verify_valid_row(ndx1); - verify_valid_row(ndx2); - m_link_view->swap(ndx1, ndx2); -} - -void List::delete_all() -{ - verify_in_transaction(); - m_link_view->remove_all_target_rows(); -} - -Results List::sort(SortDescriptor order) -{ - verify_attached(); - return Results(m_realm, m_link_view, util::none, std::move(order)); -} - -Results List::filter(Query q) -{ - verify_attached(); - return Results(m_realm, m_link_view, get_query().and_query(std::move(q))); -} - -Results List::snapshot() const -{ - verify_attached(); - return Results(m_realm, m_link_view).snapshot(); -} - -// These definitions rely on that LinkViews are interned by core -bool List::operator==(List const& rgt) const noexcept -{ - return m_link_view.get() == rgt.m_link_view.get(); -} - -namespace std { -size_t hash::operator()(realm::List const& list) const -{ - return std::hash()(list.m_link_view.get()); -} -} - -NotificationToken List::add_notification_callback(CollectionChangeCallback cb) -{ - verify_attached(); - if (!m_notifier) { - m_notifier = std::make_shared(m_link_view, m_realm); - RealmCoordinator::register_notifier(m_notifier); - } - return {m_notifier, m_notifier->add_callback(std::move(cb))}; -} - -List::OutOfBoundsIndexException::OutOfBoundsIndexException(size_t r, size_t c) -: std::out_of_range(util::format("Requested index %1 greater than max %2", r, c)) -, requested(r), valid_count(c) {} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp deleted file mode 100644 index 269dd5b..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp +++ /dev/null @@ -1,227 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "object_schema.hpp" - -#include "object_store.hpp" -#include "property.hpp" -#include "schema.hpp" - -#include "util/format.hpp" - -#include -#include -#include - -using namespace realm; - -#define ASSERT_PROPERTY_TYPE_VALUE(property, type) \ - static_assert(static_cast(PropertyType::property) == type_##type, \ - "PropertyType and DataType must have the same values") - -ASSERT_PROPERTY_TYPE_VALUE(Int, Int); -ASSERT_PROPERTY_TYPE_VALUE(Bool, Bool); -ASSERT_PROPERTY_TYPE_VALUE(Float, Float); -ASSERT_PROPERTY_TYPE_VALUE(Double, Double); -ASSERT_PROPERTY_TYPE_VALUE(Data, Binary); -ASSERT_PROPERTY_TYPE_VALUE(Date, Timestamp); -ASSERT_PROPERTY_TYPE_VALUE(Any, Mixed); -ASSERT_PROPERTY_TYPE_VALUE(Object, Link); -ASSERT_PROPERTY_TYPE_VALUE(Array, LinkList); - -ObjectSchema::ObjectSchema() = default; -ObjectSchema::~ObjectSchema() = default; - -ObjectSchema::ObjectSchema(std::string name, std::initializer_list persisted_properties) -: name(std::move(name)) -, persisted_properties(persisted_properties) -{ - for (auto const& prop : persisted_properties) { - if (prop.is_primary) { - primary_key = prop.name; - } - } -} - -ObjectSchema::ObjectSchema(Group const& group, StringData name, size_t index) : name(name) { - ConstTableRef table; - if (index < group.size()) { - table = group.get_table(index); - } - else { - table = ObjectStore::table_for_object_type(group, name); - } - - size_t count = table->get_column_count(); - persisted_properties.reserve(count); - for (size_t col = 0; col < count; col++) { - Property property; - property.name = table->get_column_name(col).data(); - property.type = (PropertyType)table->get_column_type(col); - property.is_indexed = table->has_search_index(col); - property.is_nullable = table->is_nullable(col) || property.type == PropertyType::Object; - property.table_column = col; - if (property.type == PropertyType::Object || property.type == PropertyType::Array) { - // set link type for objects and arrays - ConstTableRef linkTable = table->get_link_target(col); - property.object_type = ObjectStore::object_type_for_table_name(linkTable->get_name().data()); - } - persisted_properties.push_back(std::move(property)); - } - - primary_key = realm::ObjectStore::get_primary_key_for_object(group, name); - set_primary_key_property(); -} - -Property *ObjectSchema::property_for_name(StringData name) { - for (auto& prop : persisted_properties) { - if (StringData(prop.name) == name) { - return ∝ - } - } - for (auto& prop : computed_properties) { - if (StringData(prop.name) == name) { - return ∝ - } - } - return nullptr; -} - -const Property *ObjectSchema::property_for_name(StringData name) const { - return const_cast(this)->property_for_name(name); -} - -bool ObjectSchema::property_is_computed(Property const& property) const { - auto end = computed_properties.end(); - return std::find(computed_properties.begin(), end, property) != end; -} - -void ObjectSchema::set_primary_key_property() -{ - if (primary_key.length()) { - if (auto primary_key_prop = primary_key_property()) { - primary_key_prop->is_primary = true; - } - } -} - -static void validate_property(Schema const& schema, - std::string const& object_name, - Property const& prop, - Property const** primary, - std::vector& exceptions) -{ - // check nullablity - if (prop.is_nullable && !prop.type_is_nullable()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' cannot be nullable.", - object_name, prop.name, string_for_property_type(prop.type)); - } - else if (prop.type == PropertyType::Object && !prop.is_nullable) { - exceptions.emplace_back("Property '%1.%2' of type 'Object' must be nullable.", object_name, prop.name); - } - - // check primary keys - if (prop.is_primary) { - if (!prop.is_indexable()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' cannot be made the primary key.", - object_name, prop.name, string_for_property_type(prop.type)); - } - if (*primary) { - exceptions.emplace_back("Properties'%1' and '%2' are both marked as the primary key of '%3'.", - prop.name, (*primary)->name, object_name); - } - *primary = ∝ - } - - // check indexable - if (prop.is_indexed && !prop.is_indexable()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' cannot be indexed.", - object_name, prop.name, string_for_property_type(prop.type)); - } - - // check that only link properties have object types - if (prop.type != PropertyType::LinkingObjects && !prop.link_origin_property_name.empty()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' cannot have an origin property name.", - object_name, prop.name, string_for_property_type(prop.type)); - } - else if (prop.type == PropertyType::LinkingObjects && prop.link_origin_property_name.empty()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' must have an origin property name.", - object_name, prop.name, string_for_property_type(prop.type)); - } - - if (prop.type != PropertyType::Object && prop.type != PropertyType::Array && prop.type != PropertyType::LinkingObjects) { - if (!prop.object_type.empty()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' cannot have an object type.", - object_name, prop.name, string_for_property_type(prop.type)); - } - return; - } - - - // check that the object_type is valid for link properties - auto it = schema.find(prop.object_type); - if (it == schema.end()) { - exceptions.emplace_back("Property '%1.%2' of type '%3' has unknown object type '%4'", - object_name, prop.name, string_for_property_type(prop.type), prop.object_type); - return; - } - if (prop.type != PropertyType::LinkingObjects) { - return; - } - - const Property *origin_property = it->property_for_name(prop.link_origin_property_name); - if (!origin_property) { - exceptions.emplace_back("Property '%1.%2' declared as origin of linking objects property '%3.%4' does not exist", - prop.object_type, prop.link_origin_property_name, - object_name, prop.name); - } - else if (origin_property->type != PropertyType::Object && origin_property->type != PropertyType::Array) { - exceptions.emplace_back("Property '%1.%2' declared as origin of linking objects property '%3.%4' is not a link", - prop.object_type, prop.link_origin_property_name, - object_name, prop.name); - } - else if (origin_property->object_type != object_name) { - exceptions.emplace_back("Property '%1.%2' declared as origin of linking objects property '%3.%4' links to type '%5'", - prop.object_type, prop.link_origin_property_name, - object_name, prop.name, origin_property->object_type); - } -} - -void ObjectSchema::validate(Schema const& schema, std::vector& exceptions) const -{ - const Property *primary = nullptr; - for (auto const& prop : persisted_properties) { - validate_property(schema, name, prop, &primary, exceptions); - } - for (auto const& prop : computed_properties) { - validate_property(schema, name, prop, &primary, exceptions); - } - - if (!primary_key.empty() && !primary && !primary_key_property()) { - exceptions.emplace_back("Specified primary key '%1.%2' does not exist.", name, primary_key); - } -} - -namespace realm { -bool operator==(ObjectSchema const& a, ObjectSchema const& b) -{ - return std::tie(a.name, a.primary_key, a.persisted_properties, a.computed_properties) - == std::tie(b.name, b.primary_key, b.persisted_properties, b.computed_properties); - -} -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/object_store.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/object_store.cpp deleted file mode 100644 index e9fe1cb..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/object_store.cpp +++ /dev/null @@ -1,813 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "object_store.hpp" - -#include "object_schema.hpp" -#include "schema.hpp" -#include "shared_realm.hpp" -#include "util/format.hpp" - -#include -#include -#include -#include - -#include - -using namespace realm; - -const uint64_t ObjectStore::NotVersioned = std::numeric_limits::max(); - -namespace { -const char * const c_metadataTableName = "metadata"; -const char * const c_versionColumnName = "version"; -const size_t c_versionColumnIndex = 0; - -const char * const c_primaryKeyTableName = "pk"; -const char * const c_primaryKeyObjectClassColumnName = "pk_table"; -const size_t c_primaryKeyObjectClassColumnIndex = 0; -const char * const c_primaryKeyPropertyNameColumnName = "pk_property"; -const size_t c_primaryKeyPropertyNameColumnIndex = 1; - -const size_t c_zeroRowIndex = 0; - -const char c_object_table_prefix[] = "class_"; - -void create_metadata_tables(Group& group) { - TableRef table = group.get_or_add_table(c_primaryKeyTableName); - if (table->get_column_count() == 0) { - table->add_column(type_String, c_primaryKeyObjectClassColumnName); - table->add_column(type_String, c_primaryKeyPropertyNameColumnName); - } - table->add_search_index(table->get_column_index(c_primaryKeyObjectClassColumnName)); - - table = group.get_or_add_table(c_metadataTableName); - if (table->get_column_count() == 0) { - table->add_column(type_Int, c_versionColumnName); - - // set initial version - table->add_empty_row(); - table->set_int(c_versionColumnIndex, c_zeroRowIndex, ObjectStore::NotVersioned); - } -} - -void set_schema_version(Group& group, uint64_t version) { - TableRef table = group.get_or_add_table(c_metadataTableName); - table->set_int(c_versionColumnIndex, c_zeroRowIndex, version); -} - -template -auto table_for_object_schema(Group& group, ObjectSchema const& object_schema) -{ - return ObjectStore::table_for_object_type(group, object_schema.name); -} - -void add_index(Table& table, size_t col) -{ - try { - table.add_search_index(col); - } - catch (LogicError const&) { - throw std::logic_error(util::format("Cannot index property '%1.%2': indexing properties of type '%3' is not yet implemented.", - ObjectStore::object_type_for_table_name(table.get_name()), - table.get_column_name(col), - string_for_property_type((PropertyType)table.get_column_type(col)))); - } -} - -void insert_column(Group& group, Table& table, Property const& property, size_t col_ndx) -{ - // Cannot directly insert a LinkingObjects column (a computed property). - // LinkingObjects must be an artifact of an existing link column. - REALM_ASSERT(property.type != PropertyType::LinkingObjects); - - if (property.type == PropertyType::Object || property.type == PropertyType::Array) { - auto target_name = ObjectStore::table_name_for_object_type(property.object_type); - TableRef link_table = group.get_or_add_table(target_name); - table.insert_column_link(col_ndx, DataType(property.type), property.name, *link_table); - } - else { - table.insert_column(col_ndx, DataType(property.type), property.name, property.is_nullable); - if (property.requires_index()) - add_index(table, col_ndx); - } -} - -void add_column(Group& group, Table& table, Property const& property) -{ - insert_column(group, table, property, table.get_column_count()); -} - -void replace_column(Group& group, Table& table, Property const& old_property, Property const& new_property) -{ - insert_column(group, table, new_property, old_property.table_column); - table.remove_column(old_property.table_column + 1); -} - -TableRef create_table(Group& group, ObjectSchema const& object_schema) -{ - auto name = ObjectStore::table_name_for_object_type(object_schema.name); - auto table = group.get_or_add_table(name); - if (table->get_column_count() > 0) { - return table; - } - - for (auto const& prop : object_schema.persisted_properties) { - add_column(group, *table, prop); - } - - ObjectStore::set_primary_key_for_object(group, object_schema.name, object_schema.primary_key); - - return table; -} - -void copy_property_values(Property const& prop, Table& table) -{ - auto copy_property_values = [&](auto getter, auto setter) { - for (size_t i = 0, count = table.size(); i < count; i++) { - bool is_default = false; - (table.*setter)(prop.table_column, i, (table.*getter)(prop.table_column + 1, i), - is_default); - } - }; - - switch (prop.type) { - case PropertyType::Int: - copy_property_values(&Table::get_int, &Table::set_int); - break; - case PropertyType::Bool: - copy_property_values(&Table::get_bool, &Table::set_bool); - break; - case PropertyType::Float: - copy_property_values(&Table::get_float, &Table::set_float); - break; - case PropertyType::Double: - copy_property_values(&Table::get_double, &Table::set_double); - break; - case PropertyType::String: - copy_property_values(&Table::get_string, &Table::set_string); - break; - case PropertyType::Data: - copy_property_values(&Table::get_binary, &Table::set_binary); - break; - case PropertyType::Date: - copy_property_values(&Table::get_timestamp, &Table::set_timestamp); - break; - default: - break; - } -} - -void make_property_optional(Group& group, Table& table, Property property) -{ - property.is_nullable = true; - insert_column(group, table, property, property.table_column); - copy_property_values(property, table); - table.remove_column(property.table_column + 1); -} - -void make_property_required(Group& group, Table& table, Property property) -{ - property.is_nullable = false; - insert_column(group, table, property, property.table_column); - table.remove_column(property.table_column + 1); -} - -void validate_primary_column_uniqueness(Group const& group, StringData object_type, StringData primary_property) -{ - auto table = ObjectStore::table_for_object_type(group, object_type); - if (table->get_distinct_view(table->get_column_index(primary_property)).size() != table->size()) { - throw DuplicatePrimaryKeyValueException(object_type, primary_property); - } -} - -void validate_primary_column_uniqueness(Group const& group) -{ - auto pk_table = group.get_table(c_primaryKeyTableName); - for (size_t i = 0, count = pk_table->size(); i < count; ++i) { - validate_primary_column_uniqueness(group, - pk_table->get_string(c_primaryKeyObjectClassColumnIndex, i), - pk_table->get_string(c_primaryKeyPropertyNameColumnIndex, i)); - } -} -} // anonymous namespace - -uint64_t ObjectStore::get_schema_version(Group const& group) { - ConstTableRef table = group.get_table(c_metadataTableName); - if (!table || table->get_column_count() == 0) { - return ObjectStore::NotVersioned; - } - return table->get_int(c_versionColumnIndex, c_zeroRowIndex); -} - -StringData ObjectStore::get_primary_key_for_object(Group const& group, StringData object_type) { - ConstTableRef table = group.get_table(c_primaryKeyTableName); - if (!table) { - return ""; - } - size_t row = table->find_first_string(c_primaryKeyObjectClassColumnIndex, object_type); - if (row == not_found) { - return ""; - } - return table->get_string(c_primaryKeyPropertyNameColumnIndex, row); -} - -void ObjectStore::set_primary_key_for_object(Group& group, StringData object_type, StringData primary_key) { - TableRef table = group.get_table(c_primaryKeyTableName); - - // get row or create if new object and populate - size_t row = table->find_first_string(c_primaryKeyObjectClassColumnIndex, object_type); - if (row == not_found && primary_key.size()) { - row = table->add_empty_row(); - row = table->set_string_unique(c_primaryKeyObjectClassColumnIndex, row, object_type); - } - - // set if changing, or remove if setting to nil - if (primary_key.size() == 0) { - if (row != not_found) { - table->move_last_over(row); - } - } - else { - table->set_string(c_primaryKeyPropertyNameColumnIndex, row, primary_key); - } -} - -StringData ObjectStore::object_type_for_table_name(StringData table_name) { - if (table_name.begins_with(c_object_table_prefix)) { - return table_name.substr(sizeof(c_object_table_prefix) - 1); - } - return StringData(); -} - -std::string ObjectStore::table_name_for_object_type(StringData object_type) { - return std::string(c_object_table_prefix) + std::string(object_type); -} - -TableRef ObjectStore::table_for_object_type(Group& group, StringData object_type) { - auto name = table_name_for_object_type(object_type); - return group.get_table(name); -} - -ConstTableRef ObjectStore::table_for_object_type(Group const& group, StringData object_type) { - auto name = table_name_for_object_type(object_type); - return group.get_table(name); -} - -namespace { -struct SchemaDifferenceExplainer { - std::vector errors; - - void operator()(schema_change::AddTable op) - { - errors.emplace_back("Class '%1' has been added.", op.object->name); - } - - void operator()(schema_change::AddProperty op) - { - errors.emplace_back("Property '%1.%2' has been added.", op.object->name, op.property->name); - } - - void operator()(schema_change::RemoveProperty op) - { - errors.emplace_back("Property '%1.%2' has been removed.", op.object->name, op.property->name); - } - - void operator()(schema_change::ChangePropertyType op) - { - errors.emplace_back("Property '%1.%2' has been changed from '%3' to '%4'.", - op.object->name, op.new_property->name, - string_for_property_type(op.old_property->type), - string_for_property_type(op.new_property->type)); - } - - void operator()(schema_change::MakePropertyNullable op) - { - errors.emplace_back("Property '%1.%2' has been made optional.", op.object->name, op.property->name); - } - - void operator()(schema_change::MakePropertyRequired op) - { - errors.emplace_back("Property '%1.%2' has been made required.", op.object->name, op.property->name); - } - - void operator()(schema_change::ChangePrimaryKey op) - { - if (op.property && !op.object->primary_key.empty()) { - errors.emplace_back("Primary Key for class '%1 has changed from '%2' to '%3'.", - op.object->name, op.object->primary_key, op.property->name); - } - else if (op.property) { - errors.emplace_back("Primary Key for class '%1 has been added.", op.object->name); - } - else { - errors.emplace_back("Primary Key for class '%1 has been removed.", op.object->name); - } - } - - void operator()(schema_change::AddIndex op) - { - errors.emplace_back("Property '%1.%2' has been made indexed.", op.object->name, op.property->name); - } - - void operator()(schema_change::RemoveIndex op) - { - errors.emplace_back("Property '%1.%2' has been made unindexed.", op.object->name, op.property->name); - } -}; - -class TableHelper { -public: - TableHelper(Group& g) : m_group(g) { } - - Table& operator()(const ObjectSchema* object_schema) - { - if (object_schema != m_current_object_schema) { - m_current_table = table_for_object_schema(m_group, *object_schema); - m_current_object_schema = object_schema; - } - REALM_ASSERT(m_current_table); - return *m_current_table; - } - -private: - Group& m_group; - const ObjectSchema* m_current_object_schema = nullptr; - TableRef m_current_table; -}; - -template -void verify_no_errors(Verifier&& verifier, std::vector const& changes) -{ - for (auto& change : changes) { - change.visit(verifier); - } - - if (!verifier.errors.empty()) { - throw ErrorType(verifier.errors); - } -} -} // anonymous namespace - -bool ObjectStore::needs_migration(std::vector const& changes) -{ - using namespace schema_change; - struct Visitor { - bool operator()(AddIndex) { return false; } - bool operator()(AddProperty) { return true; } - bool operator()(AddTable) { return false; } - bool operator()(ChangePrimaryKey) { return true; } - bool operator()(ChangePropertyType) { return true; } - bool operator()(MakePropertyNullable) { return true; } - bool operator()(MakePropertyRequired) { return true; } - bool operator()(RemoveIndex) { return false; } - bool operator()(RemoveProperty) { return true; } - }; - - return std::any_of(begin(changes), end(changes), - [](auto&& change) { return change.visit(Visitor()); }); -} - -void ObjectStore::verify_no_changes_required(std::vector const& changes) -{ - verify_no_errors(SchemaDifferenceExplainer(), changes); -} - -void ObjectStore::verify_no_migration_required(std::vector const& changes) -{ - using namespace schema_change; - struct Verifier : SchemaDifferenceExplainer { - using SchemaDifferenceExplainer::operator(); - - // Adding a table or adding/removing indexes can be done automatically. - // All other changes require migrations. - void operator()(AddTable) { } - void operator()(AddIndex) { } - void operator()(RemoveIndex) { } - } verifier; - verify_no_errors(verifier, changes); -} - -void ObjectStore::verify_valid_additive_changes(std::vector const& changes) -{ - using namespace schema_change; - struct Verifier : SchemaDifferenceExplainer { - using SchemaDifferenceExplainer::operator(); - - // Additive mode allows adding things, extra columns, and adding/removing indexes - void operator()(AddTable) { } - void operator()(AddProperty) { } - void operator()(RemoveProperty) { } - void operator()(AddIndex) { } - void operator()(RemoveIndex) { } - } verifier; - verify_no_errors(verifier, changes); -} - -static void apply_non_migration_changes(Group& group, std::vector const& changes) -{ - using namespace schema_change; - struct Applier : SchemaDifferenceExplainer { - Applier(Group& group) : group{group}, table{group} { } - Group& group; - TableHelper table; - - // Produce an exception listing the unsupported schema changes for - // everything but the explicitly supported ones - using SchemaDifferenceExplainer::operator(); - - void operator()(AddTable op) { create_table(group, *op.object); } - void operator()(AddIndex op) { add_index(table(op.object), op.property->table_column); } - void operator()(RemoveIndex op) { table(op.object).remove_search_index(op.property->table_column); } - } applier{group}; - verify_no_errors(applier, changes); -} - -static void create_initial_tables(Group& group, std::vector const& changes) -{ - using namespace schema_change; - struct Applier { - Applier(Group& group) : group{group}, table{group} { } - Group& group; - TableHelper table; - - void operator()(AddTable op) { create_table(group, *op.object); } - - // Note that in normal operation none of these will be hit, as if we're - // creating the initial tables there shouldn't be anything to update. - // Implementing these makes us better able to handle weird - // not-quite-correct files produced by other things and has no obvious - // downside. - void operator()(AddProperty op) { add_column(group, table(op.object), *op.property); } - void operator()(RemoveProperty op) { table(op.object).remove_column(op.property->table_column); } - void operator()(MakePropertyNullable op) { make_property_optional(group, table(op.object), *op.property); } - void operator()(MakePropertyRequired op) { make_property_required(group, table(op.object), *op.property); } - void operator()(ChangePrimaryKey op) { ObjectStore::set_primary_key_for_object(group, op.object->name, op.property ? StringData{op.property->name} : ""); } - void operator()(AddIndex op) { add_index(table(op.object), op.property->table_column); } - void operator()(RemoveIndex op) { table(op.object).remove_search_index(op.property->table_column); } - - void operator()(ChangePropertyType op) - { - replace_column(group, table(op.object), *op.old_property, *op.new_property); - } - } applier{group}; - - for (auto& change : changes) { - change.visit(applier); - } -} - -static void apply_additive_changes(Group& group, std::vector const& changes, bool update_indexes) -{ - using namespace schema_change; - struct Applier { - Applier(Group& group, bool update_indexes) : group{group}, table{group}, update_indexes{update_indexes} { } - Group& group; - TableHelper table; - bool update_indexes; - - void operator()(AddTable op) { create_table(group, *op.object); } - void operator()(AddProperty op) { add_column(group, table(op.object), *op.property); } - void operator()(AddIndex op) { if (update_indexes) add_index(table(op.object), op.property->table_column); } - void operator()(RemoveIndex op) { if (update_indexes) table(op.object).remove_search_index(op.property->table_column); } - void operator()(RemoveProperty) { } - - // No need for errors for these, as we've already verified that they aren't present - void operator()(ChangePrimaryKey) { } - void operator()(ChangePropertyType) { } - void operator()(MakePropertyNullable) { } - void operator()(MakePropertyRequired) { } - } applier{group, update_indexes}; - - for (auto& change : changes) { - change.visit(applier); - } -} - -static void apply_pre_migration_changes(Group& group, std::vector const& changes) -{ - using namespace schema_change; - struct Applier { - Applier(Group& group) : group{group}, table{group} { } - Group& group; - TableHelper table; - - void operator()(AddTable op) { create_table(group, *op.object); } - void operator()(AddProperty op) { add_column(group, table(op.object), *op.property); } - void operator()(RemoveProperty) { /* delayed until after the migration */ } - void operator()(ChangePropertyType op) { replace_column(group, table(op.object), *op.old_property, *op.new_property); } - void operator()(MakePropertyNullable op) { make_property_optional(group, table(op.object), *op.property); } - void operator()(MakePropertyRequired op) { make_property_required(group, table(op.object), *op.property); } - void operator()(ChangePrimaryKey op) { ObjectStore::set_primary_key_for_object(group, op.object->name, op.property ? op.property->name : ""); } - void operator()(AddIndex op) { add_index(table(op.object), op.property->table_column); } - void operator()(RemoveIndex op) { table(op.object).remove_search_index(op.property->table_column); } - } applier{group}; - - for (auto& change : changes) { - change.visit(applier); - } -} - -static void apply_post_migration_changes(Group& group, std::vector const& changes, Schema const& initial_schema) -{ - using namespace schema_change; - struct Applier { - Applier(Group& group, Schema const& initial_schema) : group{group}, initial_schema(initial_schema), table(group) { } - Group& group; - Schema const& initial_schema; - TableHelper table; - - void operator()(RemoveProperty op) - { - if (!initial_schema.empty() && !initial_schema.find(op.object->name)->property_for_name(op.property->name)) - throw std::logic_error(util::format("Renamed property '%1.%2' does not exist.", op.object->name, op.property->name)); - auto table = table_for_object_schema(group, *op.object); - table->remove_column(op.property->table_column); - } - - void operator()(ChangePrimaryKey op) - { - if (op.property) { - validate_primary_column_uniqueness(group, op.object->name, op.property->name); - } - } - - void operator()(AddTable op) { create_table(group, *op.object); } - void operator()(AddIndex op) { add_index(table(op.object), op.property->table_column); } - void operator()(RemoveIndex op) { table(op.object).remove_search_index(op.property->table_column); } - - void operator()(ChangePropertyType) { } - void operator()(MakePropertyNullable) { } - void operator()(MakePropertyRequired) { } - void operator()(AddProperty) { } - } applier{group, initial_schema}; - - for (auto& change : changes) { - change.visit(applier); - } -} - -void ObjectStore::apply_schema_changes(Group& group, Schema& schema, uint64_t& schema_version, - Schema const& target_schema, uint64_t target_schema_version, - SchemaMode mode, std::vector const& changes, - std::function migration_function) -{ - create_metadata_tables(group); - - if (schema_version == ObjectStore::NotVersioned) { - create_initial_tables(group, changes); - set_schema_version(group, target_schema_version); - schema_version = target_schema_version; - schema = target_schema; - set_schema_columns(group, schema); - return; - } - - if (mode == SchemaMode::Additive) { - apply_additive_changes(group, changes, schema_version < target_schema_version); - - if (schema_version < target_schema_version) { - schema_version = target_schema_version; - set_schema_version(group, target_schema_version); - } - - schema = target_schema; - set_schema_columns(group, schema); - return; - } - - if (mode == SchemaMode::Manual) { - // Have to update the schema on the Realm before calling the migration - // function as the migration will need it - auto old_version = schema_version; - auto old_schema = schema; - schema_version = target_schema_version; - schema = target_schema; - set_schema_columns(group, schema); - - try { - migration_function(); - verify_no_changes_required(schema_from_group(group).compare(schema)); - validate_primary_column_uniqueness(group); - } - catch (...) { - schema = move(old_schema); - schema_version = old_version; - throw; - } - - set_schema_columns(group, schema); - set_schema_version(group, target_schema_version); - return; - } - - if (schema_version == target_schema_version) { - apply_non_migration_changes(group, changes); - schema = target_schema; - set_schema_columns(group, schema); - return; - } - - apply_pre_migration_changes(group, changes); - if (migration_function) { - // Have to update the schema on the Realm before calling the migration - // function as the migration will need it - auto old_version = schema_version; - auto old_schema = schema; - schema_version = target_schema_version; - schema = target_schema; - set_schema_columns(group, schema); - - try { - migration_function(); - - // Migration function may have changed the schema, so we need to re-read it - schema = schema_from_group(group); - apply_post_migration_changes(group, schema.compare(target_schema), old_schema); - validate_primary_column_uniqueness(group); - } - catch (...) { - schema = move(old_schema); - schema_version = old_version; - throw; - } - } - else { - apply_post_migration_changes(group, changes, {}); - } - - set_schema_version(group, target_schema_version); - schema_version = target_schema_version; - schema = target_schema; - set_schema_columns(group, schema); -} - -Schema ObjectStore::schema_from_group(Group const& group) { - std::vector schema; - schema.reserve(group.size()); - for (size_t i = 0; i < group.size(); i++) { - auto object_type = object_type_for_table_name(group.get_table_name(i)); - if (object_type.size()) { - schema.emplace_back(group, object_type, i); - } - } - return schema; -} - -void ObjectStore::set_schema_columns(Group const& group, Schema& schema) -{ - for (auto& object_schema : schema) { - auto table = table_for_object_schema(group, object_schema); - if (!table) { - continue; - } - for (auto& property : object_schema.persisted_properties) { - property.table_column = table->get_column_index(property.name); - } - } -} - -void ObjectStore::delete_data_for_object(Group& group, StringData object_type) { - if (TableRef table = table_for_object_type(group, object_type)) { - group.remove_table(table->get_index_in_group()); - ObjectStore::set_primary_key_for_object(group, object_type, ""); - } -} - -bool ObjectStore::is_empty(Group const& group) { - for (size_t i = 0; i < group.size(); i++) { - ConstTableRef table = group.get_table(i); - std::string object_type = object_type_for_table_name(table->get_name()); - if (!object_type.length()) { - continue; - } - if (!table->is_empty()) { - return false; - } - } - return true; -} - -void ObjectStore::rename_property(Group& group, Schema& target_schema, StringData object_type, StringData old_name, StringData new_name) -{ - TableRef table = table_for_object_type(group, object_type); - if (!table) { - throw std::logic_error(util::format("Cannot rename properties for type '%1' because it does not exist.", object_type)); - } - - auto target_object_schema = target_schema.find(object_type); - if (target_object_schema == target_schema.end()) { - throw std::logic_error(util::format("Cannot rename properties for type '%1' because it has been removed from the Realm.", object_type)); - } - - if (target_object_schema->property_for_name(old_name)) { - throw std::logic_error(util::format("Cannot rename property '%1.%2' to '%3' because the source property still exists.", - object_type, old_name, new_name)); - } - - ObjectSchema table_object_schema(group, object_type); - Property *old_property = table_object_schema.property_for_name(old_name); - if (!old_property) { - throw std::logic_error(util::format("Cannot rename property '%1.%2' because it does not exist.", object_type, old_name)); - } - - Property *new_property = table_object_schema.property_for_name(new_name); - if (!new_property) { - // New property doesn't exist in the table, which means we're probably - // renaming to an intermediate property in a multi-version migration. - // This is safe because the migration will fail schema validation unless - // this property is renamed again to a valid name before the end. - table->rename_column(old_property->table_column, new_name); - return; - } - - if (old_property->type != new_property->type || old_property->object_type != new_property->object_type) { - throw std::logic_error(util::format("Cannot rename property '%1.%2' to '%3' because it would change from type '%4' to '%5'.", - object_type, old_name, new_name, old_property->type_string(), new_property->type_string())); - } - - if (old_property->is_nullable && !new_property->is_nullable) { - throw std::logic_error(util::format("Cannot rename property '%1.%2' to '%3' because it would change from optional to required.", - object_type, old_name, new_name)); - } - - size_t column_to_remove = new_property->table_column; - table->rename_column(old_property->table_column, new_name); - table->remove_column(column_to_remove); - - // update table_column for each property since it may have shifted - for (auto& current_prop : target_object_schema->persisted_properties) { - if (current_prop.table_column == column_to_remove) - current_prop.table_column = old_property->table_column; - else if (current_prop.table_column > column_to_remove) - --current_prop.table_column; - } - - // update nullability for column - if (new_property->is_nullable && !old_property->is_nullable) { - auto prop = *new_property; - prop.table_column = old_property->table_column; - make_property_optional(group, *table, prop); - } -} - -InvalidSchemaVersionException::InvalidSchemaVersionException(uint64_t old_version, uint64_t new_version) -: logic_error(util::format("Provided schema version %1 is less than last set version %2.", new_version, old_version)) -, m_old_version(old_version), m_new_version(new_version) -{ -} - -DuplicatePrimaryKeyValueException::DuplicatePrimaryKeyValueException(std::string object_type, std::string property) -: logic_error(util::format("Primary key property '%1.%2' has duplicate values after migration.", object_type, property)) -, m_object_type(object_type), m_property(property) -{ -} - -SchemaValidationException::SchemaValidationException(std::vector const& errors) -: std::logic_error([&] { - std::string message = "Schema validation failed due to the following errors:"; - for (auto const& error : errors) { - message += std::string("\n- ") + error.what(); - } - return message; -}()) -{ -} - -SchemaMismatchException::SchemaMismatchException(std::vector const& errors) -: std::logic_error([&] { - std::string message = "Migration is required due to the following errors:"; - for (auto const& error : errors) { - message += std::string("\n- ") + error.what(); - } - return message; -}()) -{ -} - -InvalidSchemaChangeException::InvalidSchemaChangeException(std::vector const& errors) -: std::logic_error([&] { - std::string message = "The following changes cannot be made in additive-only schema mode:"; - for (auto const& error : errors) { - message += std::string("\n- ") + error.what(); - } - return message; -}()) -{ -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/placeholder.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/placeholder.cpp deleted file mode 100644 index 8936534..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/placeholder.cpp +++ /dev/null @@ -1 +0,0 @@ -// This file is intentionally left blank. diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/results.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/results.cpp deleted file mode 100644 index 51451a8..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/results.cpp +++ /dev/null @@ -1,622 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "results.hpp" - -#include "impl/realm_coordinator.hpp" -#include "impl/results_notifier.hpp" -#include "object_schema.hpp" -#include "object_store.hpp" -#include "schema.hpp" -#include "util/compiler.hpp" -#include "util/format.hpp" - -#include - -using namespace realm; - -Results::Results() = default; -Results::~Results() = default; - -Results::Results(SharedRealm r, Query q, SortDescriptor s, SortDescriptor d) -: m_realm(std::move(r)) -, m_query(std::move(q)) -, m_table(m_query.get_table().get()) -, m_sort(std::move(s)) -, m_distinct(std::move(d)) -, m_mode(Mode::Query) -{ -} - -Results::Results(SharedRealm r, Table& table) -: m_realm(std::move(r)) -, m_table(&table) -, m_mode(Mode::Table) -{ -} - -Results::Results(SharedRealm r, LinkViewRef lv, util::Optional q, SortDescriptor s) -: m_realm(std::move(r)) -, m_link_view(lv) -, m_table(&lv->get_target_table()) -, m_sort(std::move(s)) -, m_mode(Mode::LinkView) -{ - if (q) { - m_query = std::move(*q); - m_mode = Mode::Query; - } -} - -Results::Results(SharedRealm r, TableView tv, SortDescriptor s, SortDescriptor d) -: m_realm(std::move(r)) -, m_table_view(std::move(tv)) -, m_table(&m_table_view.get_parent()) -, m_sort(std::move(s)) -, m_distinct(std::move(d)) -, m_mode(Mode::TableView) -{ -} - -Results::Results(const Results&) = default; -Results& Results::operator=(const Results&) = default; - -Results::Results(Results&& other) -: m_realm(std::move(other.m_realm)) -, m_object_schema(std::move(other.m_object_schema)) -, m_query(std::move(other.m_query)) -, m_table_view(std::move(other.m_table_view)) -, m_link_view(std::move(other.m_link_view)) -, m_table(other.m_table) -, m_sort(std::move(other.m_sort)) -, m_distinct(std::move(other.m_distinct)) -, m_notifier(std::move(other.m_notifier)) -, m_mode(other.m_mode) -, m_update_policy(other.m_update_policy) -, m_has_used_table_view(other.m_has_used_table_view) -, m_wants_background_updates(other.m_wants_background_updates) -{ - if (m_notifier) { - m_notifier->target_results_moved(other, *this); - } -} - -Results& Results::operator=(Results&& other) -{ - this->~Results(); - new (this) Results(std::move(other)); - return *this; -} - -bool Results::is_valid() const -{ - if (m_realm) - m_realm->verify_thread(); - - if (m_table && !m_table->is_attached()) - return false; - - return true; -} - -void Results::validate_read() const -{ - // is_valid ensures that we're on the correct thread. - if (!is_valid()) - throw InvalidatedException(); -} - -void Results::validate_write() const -{ - validate_read(); - if (!m_realm || !m_realm->is_in_transaction()) - throw InvalidTransactionException("Must be in a write transaction"); -} - -size_t Results::size() -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: return 0; - case Mode::Table: return m_table->size(); - case Mode::LinkView: return m_link_view->size(); - case Mode::Query: - m_query.sync_view_if_needed(); - if (!m_distinct) - return m_query.count(); - REALM_FALLTHROUGH; - case Mode::TableView: - update_tableview(); - return m_table_view.size(); - } - REALM_UNREACHABLE(); -} - -const ObjectSchema& Results::get_object_schema() const -{ - validate_read(); - - if (!m_object_schema) { - REALM_ASSERT(m_realm); - auto it = m_realm->schema().find(get_object_type()); - REALM_ASSERT(it != m_realm->schema().end()); - m_object_schema = &*it; - } - - return *m_object_schema; -} - - -StringData Results::get_object_type() const noexcept -{ - if (!m_table) { - return StringData(); - } - - return ObjectStore::object_type_for_table_name(m_table->get_name()); -} - -RowExpr Results::get(size_t row_ndx) -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: break; - case Mode::Table: - if (row_ndx < m_table->size()) - return m_table->get(row_ndx); - break; - case Mode::LinkView: - if (update_linkview()) { - if (row_ndx < m_link_view->size()) - return m_link_view->get(row_ndx); - break; - } - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(); - if (row_ndx >= m_table_view.size()) - break; - if (m_update_policy == UpdatePolicy::Never && !m_table_view.is_row_attached(row_ndx)) - return {}; - return m_table_view.get(row_ndx); - } - - throw OutOfBoundsIndexException{row_ndx, size()}; -} - -util::Optional Results::first() -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: - return none; - case Mode::Table: - return m_table->size() == 0 ? util::none : util::make_optional(m_table->front()); - case Mode::LinkView: - if (update_linkview()) - return m_link_view->size() == 0 ? util::none : util::make_optional(m_link_view->get(0)); - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(); - return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front()); - } - REALM_UNREACHABLE(); -} - -util::Optional Results::last() -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: - return none; - case Mode::Table: - return m_table->size() == 0 ? util::none : util::make_optional(m_table->back()); - case Mode::LinkView: - if (update_linkview()) - return m_link_view->size() == 0 ? util::none : util::make_optional(m_link_view->get(m_link_view->size() - 1)); - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(); - return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back()); - } - REALM_UNREACHABLE(); -} - -bool Results::update_linkview() -{ - REALM_ASSERT(m_update_policy == UpdatePolicy::Auto); - - if (m_sort || m_distinct) { - m_query = get_query(); - m_mode = Mode::Query; - update_tableview(); - return false; - } - return true; -} - -void Results::update_tableview(bool wants_notifications) -{ - if (m_update_policy == UpdatePolicy::Never) { - REALM_ASSERT(m_mode == Mode::TableView); - return; - } - - switch (m_mode) { - case Mode::Empty: - case Mode::Table: - case Mode::LinkView: - return; - case Mode::Query: - m_query.sync_view_if_needed(); - m_table_view = m_query.find_all(); - if (m_sort) { - m_table_view.sort(m_sort); - } - if (m_distinct) { - m_table_view.distinct(m_distinct); - } - m_mode = Mode::TableView; - REALM_FALLTHROUGH; - case Mode::TableView: - if (wants_notifications && !m_notifier && !m_realm->is_in_transaction() && m_realm->can_deliver_notifications()) { - m_notifier = std::make_shared<_impl::ResultsNotifier>(*this); - _impl::RealmCoordinator::register_notifier(m_notifier); - } - m_has_used_table_view = true; - m_table_view.sync_if_needed(); - break; - } -} - -size_t Results::index_of(Row const& row) -{ - validate_read(); - if (!row) { - throw DetatchedAccessorException{}; - } - if (m_table && row.get_table() != m_table) { - throw IncorrectTableException( - ObjectStore::object_type_for_table_name(m_table->get_name()), - ObjectStore::object_type_for_table_name(row.get_table()->get_name()), - "Attempting to get the index of a Row of the wrong type" - ); - } - return index_of(row.get_index()); -} - -size_t Results::index_of(size_t row_ndx) -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: - return not_found; - case Mode::Table: - return row_ndx; - case Mode::LinkView: - if (update_linkview()) - return m_link_view->find(row_ndx); - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(); - return m_table_view.find_by_source_ndx(row_ndx); - } - REALM_UNREACHABLE(); -} - -template -util::Optional Results::aggregate(size_t column, bool return_none_for_empty, - const char* name, - Int agg_int, Float agg_float, - Double agg_double, Timestamp agg_timestamp) -{ - validate_read(); - if (!m_table) - return none; - if (column > m_table->get_column_count()) - throw OutOfBoundsIndexException{column, m_table->get_column_count()}; - - auto do_agg = [&](auto const& getter) -> util::Optional { - switch (m_mode) { - case Mode::Empty: - return none; - case Mode::Table: - if (return_none_for_empty && m_table->size() == 0) - return none; - return util::Optional(getter(*m_table)); - case Mode::LinkView: - m_query = this->get_query(); - m_mode = Mode::Query; - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - this->update_tableview(); - if (return_none_for_empty && m_table_view.size() == 0) - return none; - return util::Optional(getter(m_table_view)); - } - REALM_UNREACHABLE(); - }; - - switch (m_table->get_column_type(column)) - { - case type_Timestamp: return do_agg(agg_timestamp); - case type_Double: return do_agg(agg_double); - case type_Float: return do_agg(agg_float); - case type_Int: return do_agg(agg_int); - default: - throw UnsupportedColumnTypeException{column, m_table, name}; - } -} - -util::Optional Results::max(size_t column) -{ - return aggregate(column, true, "max", - [=](auto const& table) { return table.maximum_int(column); }, - [=](auto const& table) { return table.maximum_float(column); }, - [=](auto const& table) { return table.maximum_double(column); }, - [=](auto const& table) { return table.maximum_timestamp(column); }); -} - -util::Optional Results::min(size_t column) -{ - return aggregate(column, true, "min", - [=](auto const& table) { return table.minimum_int(column); }, - [=](auto const& table) { return table.minimum_float(column); }, - [=](auto const& table) { return table.minimum_double(column); }, - [=](auto const& table) { return table.minimum_timestamp(column); }); -} - -util::Optional Results::sum(size_t column) -{ - return aggregate(column, false, "sum", - [=](auto const& table) { return table.sum_int(column); }, - [=](auto const& table) { return table.sum_float(column); }, - [=](auto const& table) { return table.sum_double(column); }, - [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table, "sum"}; }); -} - -util::Optional Results::average(size_t column) -{ - return aggregate(column, true, "average", - [=](auto const& table) { return table.average_int(column); }, - [=](auto const& table) { return table.average_float(column); }, - [=](auto const& table) { return table.average_double(column); }, - [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table, "average"}; }); -} - -void Results::clear() -{ - switch (m_mode) { - case Mode::Empty: - return; - case Mode::Table: - validate_write(); - m_table->clear(); - break; - case Mode::Query: - // Not using Query:remove() because building the tableview and - // clearing it is actually significantly faster - case Mode::TableView: - validate_write(); - update_tableview(); - - switch (m_update_policy) { - case UpdatePolicy::Auto: - m_table_view.clear(RemoveMode::unordered); - break; - case UpdatePolicy::Never: { - // Copy the TableView because a frozen Results shouldn't let its size() change. - TableView copy(m_table_view); - copy.clear(RemoveMode::unordered); - break; - } - } - break; - case Mode::LinkView: - validate_write(); - m_link_view->remove_all_target_rows(); - break; - } -} - -Query Results::get_query() const -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: - case Mode::Query: - return m_query; - case Mode::TableView: { - // A TableView has an associated Query if it was produced by Query::find_all. This is indicated - // by TableView::get_query returning a Query with a non-null table. - Query query = m_table_view.get_query(); - if (query.get_table()) { - return query; - } - - // The TableView has no associated query so create one with no conditions that is restricted - // to the rows in the TableView. - if (m_update_policy == UpdatePolicy::Auto) { - m_table_view.sync_if_needed(); - } - return Query(*m_table, std::unique_ptr(new TableView(m_table_view))); - } - case Mode::LinkView: - return m_table->where(m_link_view); - case Mode::Table: - return m_table->where(); - } - REALM_UNREACHABLE(); -} - -TableView Results::get_tableview() -{ - validate_read(); - switch (m_mode) { - case Mode::Empty: - return {}; - case Mode::LinkView: - if (update_linkview()) - return m_table->where(m_link_view).find_all(); - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(); - return m_table_view; - case Mode::Table: - return m_table->where().find_all(); - } - REALM_UNREACHABLE(); -} - -Results Results::sort(realm::SortDescriptor&& sort) const -{ - return Results(m_realm, get_query(), std::move(sort), m_distinct); -} - -Results Results::filter(Query&& q) const -{ - return Results(m_realm, get_query().and_query(std::move(q)), m_sort, m_distinct); -} - - -// FIXME: The current implementation of distinct() breaks the Results API. -// This is tracked by the following issues: -// - https://github.com/realm/realm-object-store/issues/266 -// - https://github.com/realm/realm-core/issues/2332 -Results Results::distinct(realm::SortDescriptor&& uniqueness) -{ - auto tv = get_tableview(); - tv.distinct(uniqueness); - return Results(m_realm, std::move(tv), m_sort, std::move(uniqueness)); -} - -Results Results::snapshot() const & -{ - validate_read(); - - return Results(*this).snapshot(); -} - -Results Results::snapshot() && -{ - validate_read(); - - switch (m_mode) { - case Mode::Empty: - return Results(); - - case Mode::Table: - case Mode::LinkView: - m_query = get_query(); - m_mode = Mode::Query; - - REALM_FALLTHROUGH; - case Mode::Query: - case Mode::TableView: - update_tableview(false); - m_notifier.reset(); - m_update_policy = UpdatePolicy::Never; - return std::move(*this); - } - REALM_UNREACHABLE(); -} - -void Results::prepare_async() -{ - if (m_notifier) { - return; - } - if (m_realm->config().read_only()) { - throw InvalidTransactionException("Cannot create asynchronous query for read-only Realms"); - } - if (m_realm->is_in_transaction()) { - throw InvalidTransactionException("Cannot create asynchronous query while in a write transaction"); - } - if (m_update_policy == UpdatePolicy::Never) { - throw std::logic_error("Cannot create asynchronous query for snapshotted Results."); - } - - m_wants_background_updates = true; - m_notifier = std::make_shared<_impl::ResultsNotifier>(*this); - _impl::RealmCoordinator::register_notifier(m_notifier); -} - -NotificationToken Results::async(std::function target) -{ - prepare_async(); - auto wrap = [=](CollectionChangeSet, std::exception_ptr e) { target(e); }; - return {m_notifier, m_notifier->add_callback(wrap)}; -} - -NotificationToken Results::add_notification_callback(CollectionChangeCallback cb) -{ - prepare_async(); - return {m_notifier, m_notifier->add_callback(std::move(cb))}; -} - -bool Results::is_in_table_order() const -{ - switch (m_mode) { - case Mode::Empty: - case Mode::Table: - return true; - case Mode::LinkView: - return false; - case Mode::Query: - return m_query.produces_results_in_table_order() && !m_sort; - case Mode::TableView: - return m_table_view.is_in_table_order(); - } - REALM_UNREACHABLE(); // keep gcc happy -} - -void Results::Internal::set_table_view(Results& results, realm::TableView &&tv) -{ - REALM_ASSERT(results.m_update_policy != UpdatePolicy::Never); - // If the previous TableView was never actually used, then stop generating - // new ones until the user actually uses the Results object again - if (results.m_mode == Mode::TableView) { - results.m_wants_background_updates = results.m_has_used_table_view; - } - - results.m_table_view = std::move(tv); - results.m_mode = Mode::TableView; - results.m_has_used_table_view = false; - REALM_ASSERT(results.m_table_view.is_in_sync()); - REALM_ASSERT(results.m_table_view.is_attached()); -} - -Results::OutOfBoundsIndexException::OutOfBoundsIndexException(size_t r, size_t c) -: std::out_of_range(util::format("Requested index %1 greater than max %2", r, c)) -, requested(r), valid_count(c) {} - -Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table, const char* operation) -: std::logic_error(util::format("Cannot %1 property '%2': operation not supported for '%3' properties", - operation, table->get_column_name(column), - string_for_property_type(static_cast(table->get_column_type(column))))) -, column_index(column) -, column_name(table->get_column_name(column)) -, column_type(table->get_column_type(column)) -{ -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/schema.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/schema.cpp deleted file mode 100644 index 0908866..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/schema.cpp +++ /dev/null @@ -1,218 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "schema.hpp" - -#include "object_schema.hpp" -#include "object_store.hpp" -#include "object_schema.hpp" -#include "property.hpp" - -#include - -using namespace realm; - -namespace realm { -bool operator==(Schema const& a, Schema const& b) -{ - return static_cast(a) == static_cast(b); -} -} - -Schema::Schema() = default; -Schema::~Schema() = default; -Schema::Schema(Schema const&) = default; -Schema::Schema(Schema &&) = default; -Schema& Schema::operator=(Schema const&) = default; -Schema& Schema::operator=(Schema&&) = default; - -Schema::Schema(std::initializer_list types) : Schema(base(types)) { } - -Schema::Schema(base types) : base(std::move(types)) -{ - std::sort(begin(), end(), [](ObjectSchema const& lft, ObjectSchema const& rgt) { - return lft.name < rgt.name; - }); -} - -Schema::iterator Schema::find(StringData name) -{ - auto it = std::lower_bound(begin(), end(), name, [](ObjectSchema const& lft, StringData rgt) { - return lft.name < rgt; - }); - if (it != end() && it->name != name) { - it = end(); - } - return it; -} - -Schema::const_iterator Schema::find(StringData name) const -{ - return const_cast(this)->find(name); -} - -Schema::iterator Schema::find(ObjectSchema const& object) noexcept -{ - return find(object.name); -} - -Schema::const_iterator Schema::find(ObjectSchema const& object) const noexcept -{ - return const_cast(this)->find(object); -} - -void Schema::validate() const -{ - std::vector exceptions; - for (auto const& object : *this) { - object.validate(*this, exceptions); - } - - if (exceptions.size()) { - throw SchemaValidationException(exceptions); - } -} - -namespace { -struct IsNotRemoveProperty { - bool operator()(SchemaChange sc) const { return sc.visit(*this); } - bool operator()(schema_change::RemoveProperty) const { return false; } - template bool operator()(T) const { return true; } -}; -struct GetRemovedColumn { - size_t operator()(SchemaChange sc) const { return sc.visit(*this); } - size_t operator()(schema_change::RemoveProperty p) const { return p.property->table_column; } - template size_t operator()(T) const { __builtin_unreachable(); } -}; -} - -static void compare(ObjectSchema const& existing_schema, - ObjectSchema const& target_schema, - std::vector& changes) -{ - for (auto& current_prop : existing_schema.persisted_properties) { - auto target_prop = target_schema.property_for_name(current_prop.name); - - if (!target_prop) { - changes.emplace_back(schema_change::RemoveProperty{&existing_schema, ¤t_prop}); - continue; - } - if (target_schema.property_is_computed(*target_prop)) { - changes.emplace_back(schema_change::RemoveProperty{&existing_schema, ¤t_prop}); - continue; - } - if (current_prop.type != target_prop->type || current_prop.object_type != target_prop->object_type) { - changes.emplace_back(schema_change::ChangePropertyType{&existing_schema, ¤t_prop, target_prop}); - continue; - } - if (current_prop.is_nullable != target_prop->is_nullable) { - if (current_prop.is_nullable) - changes.emplace_back(schema_change::MakePropertyRequired{&existing_schema, ¤t_prop}); - else - changes.emplace_back(schema_change::MakePropertyNullable{&existing_schema, ¤t_prop}); - } - if (target_prop->requires_index()) { - if (!current_prop.is_indexed) - changes.emplace_back(schema_change::AddIndex{&existing_schema, ¤t_prop}); - } - else if (current_prop.requires_index()) { - changes.emplace_back(schema_change::RemoveIndex{&existing_schema, ¤t_prop}); - } - } - - if (existing_schema.primary_key != target_schema.primary_key) { - changes.emplace_back(schema_change::ChangePrimaryKey{&existing_schema, target_schema.primary_key_property()}); - } - - for (auto& target_prop : target_schema.persisted_properties) { - if (!existing_schema.property_for_name(target_prop.name)) { - changes.emplace_back(schema_change::AddProperty{&existing_schema, &target_prop}); - } - } - - // Move all RemovePropertys to the end and sort in descending order of - // column index, as removing a column will shift all columns after that one - auto it = std::partition(begin(changes), end(changes), IsNotRemoveProperty{}); - std::sort(it, end(changes), - [](auto a, auto b) { return GetRemovedColumn()(a) > GetRemovedColumn()(b); }); -} - -std::vector Schema::compare(Schema const& target_schema) const -{ - std::vector changes; - for (auto &object_schema : target_schema) { - auto matching_schema = find(object_schema); - if (matching_schema == end()) { - changes.emplace_back(schema_change::AddTable{&object_schema}); - continue; - } - - ::compare(*matching_schema, object_schema, changes); - } - return changes; -} - -void Schema::copy_table_columns_from(realm::Schema const& other) -{ - for (auto& source_schema : other) { - auto matching_schema = find(source_schema); - if (matching_schema == end()) { - continue; - } - - for (auto& current_prop : source_schema.persisted_properties) { - auto target_prop = matching_schema->property_for_name(current_prop.name); - if (target_prop) { - target_prop->table_column = current_prop.table_column; - } - } - } -} - -namespace realm { -bool operator==(SchemaChange const& lft, SchemaChange const& rgt) -{ - if (lft.m_kind != rgt.m_kind) - return false; - - using namespace schema_change; - struct Visitor { - SchemaChange const& value; - - #define REALM_SC_COMPARE(type, ...) \ - bool operator()(type rgt) const \ - { \ - auto cmp = [](auto&& v) { return std::tie(__VA_ARGS__); }; \ - return cmp(value.type) == cmp(rgt); \ - } - - REALM_SC_COMPARE(AddIndex, v.object, v.property) - REALM_SC_COMPARE(AddProperty, v.object, v.property) - REALM_SC_COMPARE(AddTable, v.object) - REALM_SC_COMPARE(ChangePrimaryKey, v.object, v.property) - REALM_SC_COMPARE(ChangePropertyType, v.object, v.old_property, v.new_property) - REALM_SC_COMPARE(MakePropertyNullable, v.object, v.property) - REALM_SC_COMPARE(MakePropertyRequired, v.object, v.property) - REALM_SC_COMPARE(RemoveIndex, v.object, v.property) - REALM_SC_COMPARE(RemoveProperty, v.object, v.property) - - #undef REALM_SC_COMPARE - } visitor{lft}; - return rgt.visit(visitor); -} -} // namespace realm diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp deleted file mode 100644 index 977328a..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp +++ /dev/null @@ -1,768 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "shared_realm.hpp" - -#include "impl/handover.hpp" -#include "impl/realm_coordinator.hpp" -#include "impl/transact_log_handler.hpp" - -#include "binding_context.hpp" -#include "object_schema.hpp" -#include "object_store.hpp" -#include "schema.hpp" -#include "thread_confined.hpp" - -#include "util/format.hpp" - -#include -#include - -#if REALM_ENABLE_SYNC -#include -#endif - -using namespace realm; -using namespace realm::_impl; - -static std::string get_initial_temporary_directory() -{ - auto tmp_dir = getenv("TMPDIR"); - if (!tmp_dir) { - return std::string(); - } - std::string tmp_dir_str(tmp_dir); - if (!tmp_dir_str.empty() && tmp_dir_str.back() != '/') { - tmp_dir_str += '/'; - } - return tmp_dir_str; -} - -static std::string temporary_directory = get_initial_temporary_directory(); - -void realm::set_temporary_directory(std::string directory_path) -{ - if (directory_path.empty()) { - throw std::invalid_argument("'directory_path` is empty."); - } - if (directory_path.back() != '/') { - throw std::invalid_argument("'directory_path` must ends with '/'."); - } - temporary_directory = std::move(directory_path); -} - -const std::string& realm::get_temporary_directory() noexcept -{ - return temporary_directory; -} - -Realm::Realm(Config config) -: m_config(std::move(config)) -{ - open_with_config(m_config, m_history, m_shared_group, m_read_only_group, this); - - if (m_read_only_group) { - m_group = m_read_only_group.get(); - } -} - -void Realm::init(std::shared_ptr<_impl::RealmCoordinator> coordinator) -{ - // if there is an existing realm at the current path steal its schema/column mapping - if (auto existing = coordinator ? coordinator->get_schema() : nullptr) { - m_schema = *existing; - m_schema_version = coordinator->get_schema_version(); - } - else { - // otherwise get the schema from the group - m_schema_version = ObjectStore::get_schema_version(read_group()); - m_schema = ObjectStore::schema_from_group(read_group()); - - if (m_shared_group) { - m_schema_transaction_version = m_shared_group->get_version_of_current_transaction().version; - m_shared_group->end_read(); - m_group = nullptr; - } - } - - m_coordinator = std::move(coordinator); - - if (m_config.schema) { - try { - auto schema = std::move(*m_config.schema); - m_config.schema = util::none; - update_schema(std::move(schema), m_config.schema_version, - std::move(m_config.migration_function)); - } - catch (...) { - m_coordinator = nullptr; // don't try to unregister in the destructor as it'll deadlock - throw; - } - } - -} - -REALM_NOINLINE static void translate_file_exception(StringData path, bool read_only=false) -{ - try { - throw; - } - catch (util::File::PermissionDenied const& ex) { - throw RealmFileException(RealmFileException::Kind::PermissionDenied, ex.get_path(), - util::format("Unable to open a realm at path '%1'. Please use a path where your app has %2 permissions.", - ex.get_path(), read_only ? "read" : "read-write"), - ex.what()); - } - catch (util::File::Exists const& ex) { - throw RealmFileException(RealmFileException::Kind::Exists, ex.get_path(), - util::format("File at path '%1' already exists.", ex.get_path()), - ex.what()); - } - catch (util::File::NotFound const& ex) { - throw RealmFileException(RealmFileException::Kind::NotFound, ex.get_path(), - util::format("Directory at path '%1' does not exist.", ex.get_path()), ex.what()); - } - catch (util::File::AccessError const& ex) { - // Errors for `open()` include the path, but other errors don't. We - // don't want two copies of the path in the error, so strip it out if it - // appears, and then include it in our prefix. - std::string underlying = ex.what(); - RealmFileException::Kind error_kind = RealmFileException::Kind::AccessError; - // FIXME: Replace this with a proper specific exception type once Core adds support for it. - if (underlying == "Bad or incompatible history type") - error_kind = RealmFileException::Kind::BadHistoryError; - auto pos = underlying.find(ex.get_path()); - if (pos != std::string::npos && pos > 0) { - // One extra char at each end for the quotes - underlying.replace(pos - 1, ex.get_path().size() + 2, ""); - } - throw RealmFileException(error_kind, ex.get_path(), - util::format("Unable to open a realm at path '%1': %2.", ex.get_path(), underlying), ex.what()); - } - catch (IncompatibleLockFile const& ex) { - throw RealmFileException(RealmFileException::Kind::IncompatibleLockFile, path, - "Realm file is currently open in another process " - "which cannot share access with this process. " - "All processes sharing a single file must be the same architecture.", - ex.what()); - } - catch (FileFormatUpgradeRequired const& ex) { - throw RealmFileException(RealmFileException::Kind::FormatUpgradeRequired, path, - "The Realm file format must be allowed to be upgraded " - "in order to proceed.", - ex.what()); - } -} - -void Realm::open_with_config(const Config& config, - std::unique_ptr& history, - std::unique_ptr& shared_group, - std::unique_ptr& read_only_group, - Realm* realm) -{ - if (config.encryption_key.data() && config.encryption_key.size() != 64) - throw InvalidEncryptionKeyException(); - if (config.schema && config.schema_version == ObjectStore::NotVersioned) - throw std::logic_error("A schema version must be specified when the schema is specified"); - if (config.schema_mode == SchemaMode::ReadOnly && config.sync_config) - throw std::logic_error("Synchronized Realms cannot be opened in read-only mode"); - if (config.schema_mode == SchemaMode::Additive && config.migration_function) - throw std::logic_error("Realms opened in Additive-only schema mode do not use a migration function"); - if (config.schema_mode == SchemaMode::ReadOnly && config.migration_function) - throw std::logic_error("Realms opened in read-only mode do not use a migration function"); - // ResetFile also won't use the migration function, but specifying one is - // allowed to simplify temporarily switching modes during development - - try { - if (config.read_only()) { - read_only_group = std::make_unique(config.path, config.encryption_key.data(), Group::mode_ReadOnly); - } - else { - bool server_synchronization_mode = bool(config.sync_config); - if (server_synchronization_mode) { -#if REALM_ENABLE_SYNC - history = realm::sync::make_sync_history(config.path); -#else - REALM_TERMINATE("Realm was not built with sync enabled"); -#endif - } - else { - history = realm::make_in_realm_history(config.path); - } - - SharedGroupOptions options; - options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly : - SharedGroupOptions::Durability::Full; - options.encryption_key = config.encryption_key.data(); - options.allow_file_format_upgrade = !config.disable_format_upgrade; - options.upgrade_callback = [&](int from_version, int to_version) { - if (realm) { - realm->upgrade_initial_version = from_version; - realm->upgrade_final_version = to_version; - } - }; - options.temp_dir = get_temporary_directory(); - shared_group = std::make_unique(*history, options); - } - } - catch (...) { - translate_file_exception(config.path, config.read_only()); - } -} - -Realm::~Realm() -{ - if (m_coordinator) { - m_coordinator->unregister_realm(this); - } -} - -Group& Realm::read_group() -{ - if (!m_group) { - m_group = &const_cast(m_shared_group->begin_read()); - add_schema_change_handler(); - } - return *m_group; -} - -void Realm::Internal::begin_read(Realm& realm, VersionID version_id) -{ - REALM_ASSERT(!realm.m_group); - realm.m_group = &const_cast(realm.m_shared_group->begin_read(version_id)); - realm.add_schema_change_handler(); -} - -SharedRealm Realm::get_shared_realm(Config config) -{ - auto coordinator = RealmCoordinator::get_coordinator(config.path); - return coordinator->get_realm(std::move(config)); -} - -void Realm::set_schema(Schema schema, uint64_t version) -{ - schema.copy_table_columns_from(m_schema); - m_schema = schema; - m_coordinator->update_schema(schema, version); -} - -bool Realm::read_schema_from_group_if_needed() -{ - // schema of read-only Realms can't change - if (m_read_only_group) - return false; - - Group& group = read_group(); - auto current_version = m_shared_group->get_version_of_current_transaction().version; - if (m_schema_transaction_version == current_version) - return false; - - m_schema = ObjectStore::schema_from_group(group); - m_schema_version = ObjectStore::get_schema_version(group); - m_schema_transaction_version = current_version; - return true; -} - -bool Realm::reset_file_if_needed(Schema& schema, uint64_t version, std::vector& required_changes) -{ - if (m_schema_version == ObjectStore::NotVersioned) - return false; - if (m_schema_version == version) { - if (required_changes.empty()) { - set_schema(std::move(schema), version); - return true; - } - if (!ObjectStore::needs_migration(required_changes)) - return false; - } - - // FIXME: this does not work if multiple processes try to open the file at - // the same time, or even multiple threads if there is not any external - // synchronization. The latter is probably fixable, but making it - // multi-process-safe requires some sort of multi-process exclusive lock - m_group = nullptr; - m_shared_group = nullptr; - m_history = nullptr; - util::File::remove(m_config.path); - - open_with_config(m_config, m_history, m_shared_group, m_read_only_group, this); - m_schema = ObjectStore::schema_from_group(read_group()); - m_schema_version = ObjectStore::get_schema_version(read_group()); - required_changes = m_schema.compare(schema); - return false; -} - -void Realm::update_schema(Schema schema, uint64_t version, MigrationFunction migration_function) -{ - schema.validate(); - read_schema_from_group_if_needed(); - std::vector required_changes = m_schema.compare(schema); - - auto no_changes_required = [&] { - switch (m_config.schema_mode) { - case SchemaMode::Automatic: - if (version < m_schema_version && m_schema_version != ObjectStore::NotVersioned) { - throw InvalidSchemaVersionException(m_schema_version, version); - } - if (version == m_schema_version) { - if (required_changes.empty()) { - set_schema(std::move(schema), version); - return true; - } - ObjectStore::verify_no_migration_required(required_changes); - } - return false; - - case SchemaMode::ReadOnly: - if (version != m_schema_version) - throw InvalidSchemaVersionException(m_schema_version, version); - ObjectStore::verify_no_migration_required(m_schema.compare(schema)); - set_schema(std::move(schema), version); - return true; - - case SchemaMode::ResetFile: - return reset_file_if_needed(schema, version, required_changes); - - case SchemaMode::Additive: - if (required_changes.empty()) { - set_schema(std::move(schema), version); - return version == m_schema_version; - } - ObjectStore::verify_valid_additive_changes(required_changes); - return false; - - case SchemaMode::Manual: - if (version < m_schema_version && m_schema_version != ObjectStore::NotVersioned) { - throw InvalidSchemaVersionException(m_schema_version, version); - } - if (version == m_schema_version) { - ObjectStore::verify_no_changes_required(required_changes); - return true; - } - return false; - } - __builtin_unreachable(); - }; - - if (no_changes_required()) - return; - // Either the schema version has changed or we need to do non-migration changes - - m_group->set_schema_change_notification_handler(nullptr); - transaction::begin_without_validation(*m_shared_group); - add_schema_change_handler(); - - // Cancel the write transaction if we exit this function before committing it - struct WriteTransactionGuard { - Realm& realm; - ~WriteTransactionGuard() { if (realm.is_in_transaction()) realm.cancel_transaction(); } - } write_transaction_guard{*this}; - - // If beginning the write transaction advanced the version, then someone else - // may have updated the schema and we need to re-read it - // We can't just begin the write transaction before checking anything because - // that means that write transactions would block opening Realms in other processes - if (read_schema_from_group_if_needed()) { - required_changes = m_schema.compare(schema); - if (no_changes_required()) - return; - } - - bool additive = m_config.schema_mode == SchemaMode::Additive; - if (migration_function && !additive) { - auto wrapper = [&] { - SharedRealm old_realm(new Realm(m_config)); - old_realm->init(nullptr); - // Need to open in read-write mode so that it uses a SharedGroup, but - // users shouldn't actually be able to write via the old realm - old_realm->m_config.schema_mode = SchemaMode::ReadOnly; - - migration_function(old_realm, shared_from_this(), m_schema); - }; - ObjectStore::apply_schema_changes(read_group(), m_schema, m_schema_version, - schema, version, m_config.schema_mode, required_changes, wrapper); - } - else { - ObjectStore::apply_schema_changes(read_group(), m_schema, m_schema_version, - schema, version, m_config.schema_mode, required_changes); - REALM_ASSERT_DEBUG(additive || (required_changes = ObjectStore::schema_from_group(read_group()).compare(schema)).empty()); - } - - commit_transaction(); - m_coordinator->update_schema(m_schema, version); -} - -void Realm::add_schema_change_handler() -{ - if (m_config.schema_mode == SchemaMode::Additive) { - m_group->set_schema_change_notification_handler([&] { - auto new_schema = ObjectStore::schema_from_group(read_group()); - auto required_changes = m_schema.compare(new_schema); - ObjectStore::verify_valid_additive_changes(required_changes); - m_schema.copy_table_columns_from(new_schema); - m_coordinator->update_schema(m_schema, m_schema_version); - }); - } -} - -static void check_read_write(Realm *realm) -{ - if (realm->config().read_only()) { - throw InvalidTransactionException("Can't perform transactions on read-only Realms."); - } -} - -void Realm::verify_thread() const -{ - if (m_thread_id != std::this_thread::get_id()) { - throw IncorrectThreadException(); - } -} - -void Realm::verify_in_write() const -{ - if (!is_in_transaction()) { - throw InvalidTransactionException("Cannot modify managed objects outside of a write transaction."); - } -} - -bool Realm::is_in_transaction() const noexcept -{ - if (!m_shared_group) { - return false; - } - return m_shared_group->get_transact_stage() == SharedGroup::transact_Writing; -} - -void Realm::begin_transaction() -{ - check_read_write(this); - verify_thread(); - - if (is_in_transaction()) { - throw InvalidTransactionException("The Realm is already in a write transaction"); - } - - // If we're already in the middle of sending notifications, just begin the - // write transaction without sending more notifications. If this actually - // advances the read version this could leave the user in an inconsistent - // state, but that's unavoidable. - if (m_is_sending_notifications) { - _impl::NotifierPackage notifiers; - transaction::begin(*m_shared_group, m_binding_context.get(), m_config.schema_mode, notifiers); - return; - } - - // make sure we have a read transaction - read_group(); - - m_is_sending_notifications = true; - auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); - - m_coordinator->promote_to_write(*this); -} - -void Realm::commit_transaction() -{ - check_read_write(this); - verify_thread(); - - if (!is_in_transaction()) { - throw InvalidTransactionException("Can't commit a non-existing write transaction"); - } - - m_coordinator->commit_write(*this); -} - -void Realm::cancel_transaction() -{ - check_read_write(this); - verify_thread(); - - if (!is_in_transaction()) { - throw InvalidTransactionException("Can't cancel a non-existing write transaction"); - } - - transaction::cancel(*m_shared_group, m_binding_context.get()); -} - -void Realm::invalidate() -{ - verify_thread(); - check_read_write(this); - - if (is_in_transaction()) { - cancel_transaction(); - } - if (!m_group) { - return; - } - - m_shared_group->end_read(); - m_group = nullptr; -} - -bool Realm::compact() -{ - verify_thread(); - - if (m_config.read_only()) { - throw InvalidTransactionException("Can't compact a read-only Realm"); - } - if (is_in_transaction()) { - throw InvalidTransactionException("Can't compact a Realm within a write transaction"); - } - - Group& group = read_group(); - for (auto &object_schema : m_schema) { - ObjectStore::table_for_object_type(group, object_schema.name)->optimize(); - } - m_shared_group->end_read(); - m_group = nullptr; - - return m_shared_group->compact(); -} - -void Realm::write_copy(StringData path, BinaryData key) -{ - if (key.data() && key.size() != 64) { - throw InvalidEncryptionKeyException(); - } - verify_thread(); - try { - read_group().write(path, key.data()); - } - catch (...) { - translate_file_exception(path); - } -} - -void Realm::notify() -{ - if (is_closed() || is_in_transaction()) { - return; - } - - verify_thread(); - - m_is_sending_notifications = true; - auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); - - if (m_shared_group->has_changed()) { // Throws - if (m_binding_context) { - m_binding_context->changes_available(); - } - if (m_auto_refresh) { - if (m_group) { - m_coordinator->advance_to_ready(*this); - } - else { - if (m_binding_context) { - m_binding_context->did_change({}, {}); - } - m_coordinator->process_available_async(*this); - } - } - } - else { - m_coordinator->process_available_async(*this); - } -} - -bool Realm::refresh() -{ - verify_thread(); - check_read_write(this); - - // can't be any new changes if we're in a write transaction - if (is_in_transaction()) { - return false; - } - // don't advance if we're already in the process of advancing as that just - // makes things needlessly complicated - if (m_is_sending_notifications) { - return false; - } - - m_is_sending_notifications = true; - auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); - - if (m_group) { - return m_coordinator->advance_to_latest(*this); - } - - // No current read transaction, so just create a new one - read_group(); - m_coordinator->process_available_async(*this); - return true; -} - -bool Realm::can_deliver_notifications() const noexcept -{ - if (m_config.read_only()) { - return false; - } - - if (m_binding_context && !m_binding_context->can_deliver_notifications()) { - return false; - } - - return true; -} - -uint64_t Realm::get_schema_version(const realm::Realm::Config &config) -{ - auto coordinator = RealmCoordinator::get_existing_coordinator(config.path); - if (coordinator) { - return coordinator->get_schema_version(); - } - - return ObjectStore::get_schema_version(Realm(config).read_group()); -} - -void Realm::close() -{ - if (m_coordinator) { - m_coordinator->unregister_realm(this); - } - - m_group = nullptr; - m_shared_group = nullptr; - m_history = nullptr; - m_read_only_group = nullptr; - m_binding_context = nullptr; - m_coordinator = nullptr; -} - -util::Optional Realm::file_format_upgraded_from_version() const -{ - if (upgrade_initial_version != upgrade_final_version) { - return upgrade_initial_version; - } - return util::none; -} - -Realm::HandoverPackage::HandoverPackage(HandoverPackage&&) = default; -Realm::HandoverPackage& Realm::HandoverPackage::operator=(HandoverPackage&&) = default; - -// Precondition: `m_version` is not greater than `new_version` -// Postcondition: `m_version` is equal to `new_version` -void Realm::HandoverPackage::advance_to_version(VersionID new_version) -{ - if (new_version == m_version_id) { - return; - } - REALM_ASSERT_DEBUG(new_version > m_version_id); - - // Open `Realm` at handover version - _impl::RealmCoordinator& coordinator = get_coordinator(); - Realm::Config config = coordinator.get_config(); - config.cache = false; - SharedRealm realm = coordinator.get_realm(config); - REALM_ASSERT(!realm->is_in_read_transaction()); - realm->m_group = &const_cast(realm->m_shared_group->begin_read(m_version_id)); - - // Import handover, advance version, and then repackage for handover - auto objects = realm->accept_handover(std::move(*this)); - transaction::advance(*realm->m_shared_group, realm->m_binding_context.get(), - realm->m_config.schema_mode, new_version); - *this = realm->package_for_handover(std::move(objects)); -} - -Realm::HandoverPackage::~HandoverPackage() -{ - if (is_awaiting_import()) { - get_coordinator().get_realm()->m_shared_group->unpin_version(m_version_id); - mark_not_awaiting_import(); - } -} - -Realm::HandoverPackage Realm::package_for_handover(std::vector objects_to_hand_over) -{ - verify_thread(); - if (is_in_transaction()) { - throw InvalidTransactionException("Cannot package handover during a write transaction."); - } - - HandoverPackage handover; - auto version_id = m_shared_group->pin_version(); - handover.m_version_id = version_id; - handover.m_source_realm = shared_from_this(); - // Since `m_source_realm` is used to determine if we need to unpin when destroyed, - // `m_source_realm` should only be set after `pin_version` succeeds in case it throws. - - handover.m_objects.reserve(objects_to_hand_over.size()); - for (auto &object : objects_to_hand_over) { - REALM_ASSERT(object.get_realm().get() == this); - handover.m_objects.push_back(object.export_for_handover()); - } - - return handover; -} - -std::vector Realm::accept_handover(Realm::HandoverPackage handover) -{ - verify_thread(); - - if (!handover.is_awaiting_import()) { - throw std::logic_error("Handover package must not be imported more than once."); - } - - auto unpin_version = util::make_scope_exit([&]() noexcept { - m_shared_group->unpin_version(handover.m_version_id); - handover.mark_not_awaiting_import(); - }); - - if (is_in_transaction()) { - throw InvalidTransactionException("Cannot accept handover during a write transaction."); - } - - // Ensure we're on the same version as the handover - if (!m_group) { - // A read transaction doesn't yet exist, so create at the handover version - m_group = &const_cast(m_shared_group->begin_read(handover.m_version_id)); - add_schema_change_handler(); - } - else { - auto current_version = m_shared_group->get_version_of_current_transaction(); - - if (handover.m_version_id <= current_version) { - // The handover is behind, so advance it to our version - handover.advance_to_version(current_version); - } else { - // We're behind, so advance to the handover's version - transaction::advance(*m_shared_group, m_binding_context.get(), - m_config.schema_mode, handover.m_version_id); - m_coordinator->process_available_async(*this); - } - } - - std::vector objects; - objects.reserve(handover.m_objects.size()); - for (auto &object : handover.m_objects) { - objects.push_back(std::move(object).import_from_handover(shared_from_this())); - } - - // Avoid weird partial-refresh semantics when importing old packages - refresh(); - - return objects; -} - -MismatchedConfigException::MismatchedConfigException(StringData message, StringData path) -: std::logic_error(util::format(message.data(), path)) { } diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp deleted file mode 100644 index 4bc0c73..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp +++ /dev/null @@ -1,296 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "sync/impl/sync_file.hpp" - -#include -#include - -using File = realm::util::File; - -namespace realm { - -namespace { - -uint8_t value_of_hex_digit(char hex_digit) -{ - if (hex_digit >= '0' && hex_digit <= '9') { - return hex_digit - '0'; - } else if (hex_digit >= 'A' && hex_digit <= 'F') { - return 10 + hex_digit - 'A'; - } else if (hex_digit >= 'a' && hex_digit <= 'f') { - return 10 + hex_digit - 'a'; - } else { - throw std::invalid_argument("Cannot get the value of a character that isn't a hex digit."); - } -} - -bool filename_is_reserved(const std::string& filename) { - return (filename == "." || filename == ".."); -} - -bool character_is_unreserved(char character) -{ - bool is_capital_letter = (character >= 'A' && character <= 'Z'); - bool is_lowercase_letter = (character >= 'a' && character <= 'z'); - bool is_number = (character >= '0' && character <= '9'); - bool is_allowed_symbol = (character == '-' || character == '_' || character == '.'); - return is_capital_letter || is_lowercase_letter || is_number || is_allowed_symbol; -} - -char decoded_char_for(const std::string& percent_encoding, size_t index) -{ - if (index+2 >= percent_encoding.length()) { - throw std::invalid_argument("Malformed string: not enough characters after '%' before end of string."); - } - REALM_ASSERT(percent_encoding[index] == '%'); - return (16*value_of_hex_digit(percent_encoding[index + 1])) + value_of_hex_digit(percent_encoding[index + 2]); -} - -} // (anonymous namespace) - -namespace util { - -void remove_nonempty_dir(const std::string& path) -{ - // Open the directory and list all the files. - DIR *dir_listing = opendir(path.c_str()); - if (!dir_listing) { - return; - } - auto cleanup = util::make_scope_exit([=]() noexcept { closedir(dir_listing); }); - while (struct dirent *file = readdir(dir_listing)) { - auto file_type = file->d_type; - std::string file_name = file->d_name; - if (file_name == "." || file_name == "..") { - continue; - } - if (file_type == DT_REG || file_type == DT_FIFO) { - File::try_remove(file_path_by_appending_component(path, file_name)); - } else if (file_type == DT_DIR) { - // Directory, recurse - remove_nonempty_dir(file_path_by_appending_component(path, file_name, FilePathType::Directory)); - } - } - // Delete the directory itself - try { - util::remove_dir(path); - } - catch (File::NotFound const&) { - } -} - -std::string make_percent_encoded_string(const std::string& raw_string) -{ - std::string buffer; - buffer.reserve(raw_string.size()); - for (size_t i=0; i 0); - if (filename_is_reserved(user_identity)) { - throw std::invalid_argument("A user can't have an identifier reserved by the filesystem."); - } - auto user_path = file_path_by_appending_component(get_base_sync_directory(), - user_identity, - util::FilePathType::Directory); - util::try_make_dir(user_path); - return user_path; -} - -void SyncFileManager::remove_user_directory(const std::string& user_identity) const -{ - REALM_ASSERT(user_identity.length() > 0); - if (filename_is_reserved(user_identity)) { - throw std::invalid_argument("A user can't have an identifier reserved by the filesystem."); - } - auto user_path = file_path_by_appending_component(get_base_sync_directory(), - user_identity, - util::FilePathType::Directory); - util::remove_nonempty_dir(user_path); -} - -bool SyncFileManager::remove_realm(const std::string& user_identity, const std::string& raw_realm_path) const -{ - REALM_ASSERT(user_identity.length() > 0); - REALM_ASSERT(raw_realm_path.length() > 0); - if (filename_is_reserved(user_identity) || filename_is_reserved(raw_realm_path)) { - throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem."); - } - auto escaped = util::make_percent_encoded_string(raw_realm_path); - auto realm_path = util::file_path_by_appending_component(user_directory(user_identity), escaped); - bool success = true; - // Remove the base Realm file (e.g. "example.realm"). - success = File::try_remove(realm_path); - // Remove the lock file (e.g. "example.realm.lock"). - auto lock_path = util::file_path_by_appending_extension(realm_path, "lock"); - success = File::try_remove(lock_path); - // Remove the management directory (e.g. "example.realm.management"). - auto management_path = util::file_path_by_appending_extension(realm_path, "management"); - try { - util::remove_nonempty_dir(management_path); - } - catch (File::NotFound const&) { - } - catch (File::AccessError const&) { - success = false; - } - return success; -} - -std::string SyncFileManager::path(const std::string& user_identity, const std::string& raw_realm_path) const -{ - REALM_ASSERT(user_identity.length() > 0); - REALM_ASSERT(raw_realm_path.length() > 0); - if (filename_is_reserved(user_identity) || filename_is_reserved(raw_realm_path)) { - throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem."); - } - auto escaped = util::make_percent_encoded_string(raw_realm_path); - auto realm_path = util::file_path_by_appending_component(user_directory(user_identity), escaped); - return realm_path; -} - -std::string SyncFileManager::metadata_path() const -{ - auto dir_path = file_path_by_appending_component(get_utility_directory(), - c_metadata_directory, - util::FilePathType::Directory); - util::try_make_dir(dir_path); - return util::file_path_by_appending_component(dir_path, c_metadata_realm); -} - -bool SyncFileManager::remove_metadata_realm() const -{ - auto dir_path = file_path_by_appending_component(get_utility_directory(), - c_metadata_directory, - util::FilePathType::Directory); - try { - util::remove_nonempty_dir(dir_path); - return true; - } - catch (File::AccessError const&) { - return false; - } -} - -} // realm diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp deleted file mode 100644 index 56c9104..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "sync/impl/sync_metadata.hpp" - -#include "object_schema.hpp" -#include "object_store.hpp" -#include "property.hpp" -#include "results.hpp" -#include "schema.hpp" -#if REALM_PLATFORM_APPLE -#include "impl/apple/keychain_helper.hpp" -#endif - -#include -#include - -namespace realm { - -static const char * const c_sync_userMetadata = "UserMetadata"; -static const char * const c_sync_marked_for_removal = "marked_for_removal"; -static const char * const c_sync_identity = "identity"; -static const char * const c_sync_auth_server_url = "auth_server_url"; -static const char * const c_sync_user_token = "user_token"; - -SyncMetadataManager::SyncMetadataManager(std::string path, - bool should_encrypt, - util::Optional> encryption_key) -{ - std::lock_guard lock(m_metadata_lock); - - auto nullable_string_property = [](const char *name) -> Property { - Property p = {name, PropertyType::String}; - p.is_nullable = true; - return p; - }; - - Property primary_key = {c_sync_identity, PropertyType::String}; - primary_key.is_indexed = true; - primary_key.is_primary = true; - - Realm::Config config; - config.path = std::move(path); - config.schema = Schema{ - {c_sync_userMetadata, { - primary_key, - {c_sync_marked_for_removal, PropertyType::Bool}, - nullable_string_property(c_sync_auth_server_url), - nullable_string_property(c_sync_user_token), - }} - }; - config.schema_mode = SchemaMode::Additive; - config.schema_version = 0; -#if REALM_PLATFORM_APPLE - if (should_encrypt && !encryption_key) { - encryption_key = keychain::metadata_realm_encryption_key(); - } -#endif - if (should_encrypt) { - if (!encryption_key) { - throw std::invalid_argument("Metadata Realm encryption was specified, but no encryption key was provided."); - } - config.encryption_key = std::move(*encryption_key); - } - - // Open the Realm. - SharedRealm realm = Realm::get_shared_realm(config); - - // Get data about the (hardcoded) schema. - DescriptorRef descriptor = ObjectStore::table_for_object_type(realm->read_group(), - c_sync_userMetadata)->get_descriptor(); - m_schema = { - descriptor->get_column_index(c_sync_identity), - descriptor->get_column_index(c_sync_marked_for_removal), - descriptor->get_column_index(c_sync_user_token), - descriptor->get_column_index(c_sync_auth_server_url) - }; - - m_metadata_config = std::move(config); -} - -Realm::Config SyncMetadataManager::get_configuration() const -{ - std::lock_guard lock(m_metadata_lock); - return m_metadata_config; -} - -SyncUserMetadataResults SyncMetadataManager::all_unmarked_users() const -{ - return get_users(false); -} - -SyncUserMetadataResults SyncMetadataManager::all_users_marked_for_removal() const -{ - return get_users(true); -} - -SyncUserMetadataResults SyncMetadataManager::get_users(bool marked) const -{ - // Open the Realm. - SharedRealm realm = Realm::get_shared_realm(get_configuration()); - - TableRef table = ObjectStore::table_for_object_type(realm->read_group(), c_sync_userMetadata); - Query query = table->where().equal(m_schema.idx_marked_for_removal, marked); - - Results results(realm, std::move(query)); - return SyncUserMetadataResults(std::move(results), std::move(realm), m_schema); -} - -SyncUserMetadata::SyncUserMetadata(Schema schema, SharedRealm realm, RowExpr row) -: m_invalid(row.get_bool(schema.idx_marked_for_removal)) -, m_schema(std::move(schema)) -, m_realm(std::move(realm)) -, m_row(row) -{ } - -SyncUserMetadata::SyncUserMetadata(const SyncMetadataManager& manager, std::string identity, bool make_if_absent) -: m_schema(manager.m_schema) -{ - // Open the Realm. - m_realm = Realm::get_shared_realm(manager.get_configuration()); - - // Retrieve or create the row for this object. - TableRef table = ObjectStore::table_for_object_type(m_realm->read_group(), c_sync_userMetadata); - size_t row_idx = table->find_first_string(m_schema.idx_identity, identity); - if (row_idx == not_found) { - if (!make_if_absent) { - m_invalid = true; - m_realm = nullptr; - return; - } - m_realm->begin_transaction(); - row_idx = table->find_first_string(m_schema.idx_identity, identity); - if (row_idx == not_found) { - row_idx = table->add_empty_row(); - table->set_string(m_schema.idx_identity, row_idx, identity); - m_realm->commit_transaction(); - } else { - // Someone beat us to adding this user. - m_realm->cancel_transaction(); - } - } - m_row = table->get(row_idx); - if (make_if_absent) { - // User existed in the table, but had been marked for deletion. Unmark it. - m_realm->begin_transaction(); - table->set_bool(m_schema.idx_marked_for_removal, row_idx, false); - m_realm->commit_transaction(); - m_invalid = false; - } else { - m_invalid = m_row.get_bool(m_schema.idx_marked_for_removal); - } -} - -bool SyncUserMetadata::is_valid() const -{ - return !m_invalid; -} - -std::string SyncUserMetadata::identity() const -{ - m_realm->verify_thread(); - StringData result = m_row.get_string(m_schema.idx_identity); - return result; -} - -util::Optional SyncUserMetadata::get_optional_string_field(size_t col_idx) const -{ - REALM_ASSERT(!m_invalid); - m_realm->verify_thread(); - StringData result = m_row.get_string(col_idx); - return result.is_null() ? util::none : util::make_optional(std::string(result)); -} - -util::Optional SyncUserMetadata::server_url() const -{ - return get_optional_string_field(m_schema.idx_auth_server_url); -} - -util::Optional SyncUserMetadata::user_token() const -{ - return get_optional_string_field(m_schema.idx_user_token); -} - -void SyncUserMetadata::set_state(util::Optional server_url, util::Optional user_token) -{ - if (m_invalid) { - return; - } - m_realm->verify_thread(); - m_realm->begin_transaction(); - m_row.set_string(m_schema.idx_user_token, *user_token); - m_row.set_string(m_schema.idx_auth_server_url, *server_url); - m_realm->commit_transaction(); -} - -void SyncUserMetadata::mark_for_removal() -{ - if (m_invalid) { - return; - } - m_realm->verify_thread(); - m_realm->begin_transaction(); - m_row.set_bool(m_schema.idx_marked_for_removal, true); - m_realm->commit_transaction(); -} - -void SyncUserMetadata::remove() -{ - m_invalid = true; - m_realm->begin_transaction(); - TableRef table = ObjectStore::table_for_object_type(m_realm->read_group(), c_sync_userMetadata); - table->move_last_over(m_row.get_index()); - m_realm->commit_transaction(); - m_realm = nullptr; -} - -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp deleted file mode 100644 index 18744e4..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp +++ /dev/null @@ -1,423 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "sync/sync_manager.hpp" - -#include "sync/impl/sync_client.hpp" -#include "sync/impl/sync_file.hpp" -#include "sync/impl/sync_metadata.hpp" -#include "sync/sync_session.hpp" -#include "sync/sync_user.hpp" - -#include - -using namespace realm; -using namespace realm::_impl; - -SyncManager& SyncManager::shared() -{ - // The singleton is heap-allocated in order to fix an issue when running unit tests where tests would crash after - // they were done running because the manager was destroyed too early. - static SyncManager& manager = *new SyncManager; - return manager; -} - -void SyncManager::configure_file_system(const std::string& base_file_path, - MetadataMode metadata_mode, - util::Optional> custom_encryption_key, - bool reset_metadata_on_error) -{ - struct UserCreationData { - std::string identity; - std::string user_token; - util::Optional server_url; - }; - - std::vector users_to_add; - { - std::lock_guard lock(m_file_system_mutex); - - // Set up the file manager. - if (m_file_manager) { - REALM_ASSERT(m_file_manager->base_path() == base_file_path); - } else { - m_file_manager = std::make_unique(base_file_path); - } - - // Set up the metadata manager, and perform initial loading/purging work. - if (m_metadata_manager) { - return; - } - switch (metadata_mode) { - case MetadataMode::NoEncryption: - m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), - false); - break; - case MetadataMode::Encryption: - try { - m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), - true, - std::move(custom_encryption_key)); - } catch (RealmFileException const& ex) { - if (reset_metadata_on_error && m_file_manager->remove_metadata_realm()) { - m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), - true, - std::move(custom_encryption_key)); - } else { - throw; - } - } - break; - case MetadataMode::NoMetadata: - return; - } - - REALM_ASSERT(m_metadata_manager); - // Load persisted users into the users map. - SyncUserMetadataResults users = m_metadata_manager->all_unmarked_users(); - for (size_t i = 0; i < users.size(); i++) { - // Note that 'admin' style users are not persisted. - auto user_data = users.get(i); - auto user_token = user_data.user_token(); - auto identity = user_data.identity(); - auto server_url = user_data.server_url(); - if (user_token) { - UserCreationData data = { std::move(identity), std::move(*user_token), std::move(server_url) }; - users_to_add.emplace_back(std::move(data)); - } - } - // Delete any users marked for death. - std::vector dead_users; - SyncUserMetadataResults users_to_remove = m_metadata_manager->all_users_marked_for_removal(); - dead_users.reserve(users_to_remove.size()); - for (size_t i = 0; i < users_to_remove.size(); i++) { - auto user = users_to_remove.get(i); - // FIXME: delete user data in a different way? (This deletes a logged-out user's data as soon as the app - // launches again, which might not be how some apps want to treat their data.) - try { - m_file_manager->remove_user_directory(user.identity()); - dead_users.emplace_back(std::move(user)); - } catch (util::File::AccessError const&) { - continue; - } - } - for (auto& user : dead_users) { - user.remove(); - } - } - { - std::lock_guard lock(m_user_mutex); - for (auto& user_data : users_to_add) { - m_users.insert({ user_data.identity, std::make_shared(user_data.user_token, - user_data.identity, - user_data.server_url) }); - } - } -} - -void SyncManager::reset_for_testing() -{ - std::lock_guard lock(m_file_system_mutex); - m_file_manager = nullptr; - m_metadata_manager = nullptr; - { - // Destroy all the users. - std::lock_guard lock(m_user_mutex); - m_users.clear(); - } - { - std::lock_guard lock(m_mutex); - - // Stop the client. This will abort any uploads that inactive sessions are waiting for. - if (m_sync_client) - m_sync_client->stop(); - - { - std::lock_guard lock(m_session_mutex); - -#if REALM_ASSERTIONS_ENABLED - // Callers of `SyncManager::reset_for_testing` should ensure there are no active sessions - // prior to calling `reset_for_testing`. - auto no_active_sessions = std::all_of(m_active_sessions.begin(), m_active_sessions.end(), [](auto& element){ - return element.second.expired(); - }); - REALM_ASSERT(no_active_sessions); -#endif - - // Destroy any remaining inactive sessions. - // FIXME: We shouldn't have any inactive sessions at this point! Sessions are expected to - // remain inactive until their final upload completes, at which point they are unregistered - // and destroyed. Our call to `sync::Client::stop` above aborts all uploads, so all sessions - // should have already been destroyed. - m_inactive_sessions.clear(); - } - - // Destroy the client now that we have no remaining sessions. - m_sync_client = nullptr; - - // Reset even more state. - // NOTE: these should always match the defaults. - m_log_level = util::Logger::Level::info; - m_logger_factory = nullptr; - m_client_reconnect_mode = sync::Client::Reconnect::normal; - m_client_validate_ssl = true; - } -} - -void SyncManager::set_log_level(util::Logger::Level level) noexcept -{ - std::lock_guard lock(m_mutex); - m_log_level = level; -} - -void SyncManager::set_logger_factory(SyncLoggerFactory& factory) noexcept -{ - std::lock_guard lock(m_mutex); - m_logger_factory = &factory; -} - -void SyncManager::set_error_handler(std::function handler) -{ - std::lock_guard lock(m_mutex); - auto wrapped_handler = [=](int error_code, std::string message) { - // FIXME: If the sync team decides to route all errors through the session-level error handler, the client-level - // error handler might go away altogether. - switch (error_code) { - case 100: // Connection closed (no error) - case 101: // Unspecified non-critical error - return; - default: - handler(error_code, message); - } - }; - m_error_handler = std::move(wrapped_handler); -} - -void SyncManager::set_client_should_reconnect_immediately(bool reconnect_immediately) -{ - std::lock_guard lock(m_mutex); - using Reconnect = sync::Client::Reconnect; - m_client_reconnect_mode = reconnect_immediately ? Reconnect::immediately : Reconnect::normal; -} - -bool SyncManager::client_should_reconnect_immediately() const noexcept -{ - std::lock_guard lock(m_mutex); - using Reconnect = sync::Client::Reconnect; - return m_client_reconnect_mode == Reconnect::immediately; -} - -void SyncManager::set_client_should_validate_ssl(bool validate_ssl) -{ - std::lock_guard lock(m_mutex); - m_client_validate_ssl = validate_ssl; -} - -bool SyncManager::client_should_validate_ssl() const noexcept -{ - std::lock_guard lock(m_mutex); - return m_client_validate_ssl; -} - -util::Logger::Level SyncManager::log_level() const noexcept -{ - std::lock_guard lock(m_mutex); - return m_log_level; -} - -bool SyncManager::perform_metadata_update(std::function update_function) const -{ - std::lock_guard lock(m_file_system_mutex); - if (!m_metadata_manager) { - return false; - } - update_function(*m_metadata_manager); - return true; -} - -std::shared_ptr SyncManager::get_user(const std::string& identity, - std::string refresh_token, - util::Optional auth_server_url, - bool is_admin) -{ - std::lock_guard lock(m_user_mutex); - auto it = m_users.find(identity); - if (it == m_users.end()) { - // No existing user. - auto new_user = std::make_shared(std::move(refresh_token), identity, auth_server_url, is_admin); - m_users.insert({ identity, new_user }); - return new_user; - } else { - auto user = it->second; - if (auth_server_url && *auth_server_url != user->server_url()) { - throw std::invalid_argument("Cannot retrieve an existing user specifying a different auth server."); - } - if (is_admin != user->is_admin()) { - throw std::invalid_argument("Cannot retrieve an existing user with a different admin status."); - } - if (user->state() == SyncUser::State::Error) { - return nullptr; - } - user->update_refresh_token(std::move(refresh_token)); - return user; - } -} - -std::shared_ptr SyncManager::get_existing_logged_in_user(const std::string& identity) const -{ - std::lock_guard lock(m_user_mutex); - auto it = m_users.find(identity); - if (it == m_users.end()) { - return nullptr; - } - auto ptr = it->second; - return (ptr->state() == SyncUser::State::Active ? ptr : nullptr); -} - -std::vector> SyncManager::all_logged_in_users() const -{ - std::lock_guard lock(m_user_mutex); - std::vector> users; - users.reserve(m_users.size()); - for (auto& it : m_users) { - auto user = it.second; - if (user->state() == SyncUser::State::Active) { - users.emplace_back(std::move(user)); - } - } - return users; -} - -std::string SyncManager::path_for_realm(const std::string& user_identity, const std::string& raw_realm_url) const -{ - std::lock_guard lock(m_file_system_mutex); - REALM_ASSERT(m_file_manager); - return m_file_manager->path(user_identity, raw_realm_url); -} - -std::shared_ptr SyncManager::get_existing_active_session(const std::string& path) const -{ - std::lock_guard lock(m_session_mutex); - return get_existing_active_session_locked(path); -} - -std::shared_ptr SyncManager::get_existing_active_session_locked(const std::string& path) const -{ - REALM_ASSERT(!m_session_mutex.try_lock()); - auto it = m_active_sessions.find(path); - if (it == m_active_sessions.end()) { - return nullptr; - } - if (auto session = it->second.lock()) { - return session; - } - return nullptr; -} - -std::unique_ptr SyncManager::get_existing_inactive_session_locked(const std::string& path) -{ - REALM_ASSERT(!m_session_mutex.try_lock()); - auto it = m_inactive_sessions.find(path); - if (it == m_inactive_sessions.end()) { - return nullptr; - } - auto ret = std::move(it->second); - m_inactive_sessions.erase(it); - return ret; -} - -std::shared_ptr SyncManager::get_session(const std::string& path, const SyncConfig& sync_config) -{ - auto& client = get_sync_client(); // Throws - - // The session is declared outside the scope of the lock so that if an exception is thrown - // it'll be destroyed after the lock has been dropped. This avoids deadlocking when - // dropped_last_reference_to_session attempts to lock the mutex. - std::shared_ptr shared_session; - - std::lock_guard lock(m_session_mutex); - if (auto session = get_existing_active_session_locked(path)) { - return session; - } - - std::unique_ptr session = get_existing_inactive_session_locked(path); - bool session_is_new = false; - if (!session) { - session_is_new = true; - session.reset(new SyncSession(client, path, sync_config)); - } - - auto session_deleter = [this](SyncSession *session) { dropped_last_reference_to_session(session); }; - shared_session = std::shared_ptr(session.release(), std::move(session_deleter)); - m_active_sessions[path] = shared_session; - if (session_is_new) { - sync_config.user->register_session(shared_session); - } else { - SyncSession::revive_if_needed(shared_session); - } - return shared_session; -} - -void SyncManager::dropped_last_reference_to_session(SyncSession* session) -{ - { - std::lock_guard lock(m_session_mutex); - auto path = session->path(); - REALM_ASSERT_DEBUG(m_active_sessions.count(path)); - m_active_sessions.erase(path); - m_inactive_sessions[path].reset(session); - } - session->close(); -} - -void SyncManager::unregister_session(const std::string& path) -{ - std::lock_guard lock(m_session_mutex); - if (m_active_sessions.count(path)) - return; - auto it = m_inactive_sessions.find(path); - REALM_ASSERT(it != m_inactive_sessions.end()); - m_inactive_sessions.erase(path); -} - -SyncClient& SyncManager::get_sync_client() const -{ - std::lock_guard lock(m_mutex); - if (!m_sync_client) - m_sync_client = create_sync_client(); // Throws - return *m_sync_client; -} - -std::unique_ptr SyncManager::create_sync_client() const -{ - REALM_ASSERT(!m_mutex.try_lock()); - - std::unique_ptr logger; - if (m_logger_factory) { - logger = m_logger_factory->make_logger(m_log_level); // Throws - } - else { - auto stderr_logger = std::make_unique(); // Throws - stderr_logger->set_level_threshold(m_log_level); - logger = std::move(stderr_logger); - } - return std::make_unique(std::move(logger), - std::move(m_error_handler), - m_client_reconnect_mode, - m_client_validate_ssl); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp deleted file mode 100644 index d8176f1..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp +++ /dev/null @@ -1,521 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "sync/sync_session.hpp" - -#include "sync/impl/sync_client.hpp" -#include "sync/sync_manager.hpp" -#include "sync/sync_user.hpp" - -#include - -using namespace realm; -using namespace realm::_impl; -using namespace realm::_impl::sync_session_states; - -/// A state which a `SyncSession` can currently be within. State classes handle various actions -/// and state transitions. -/// -/// STATES: -/// -/// WAITING_FOR_ACCESS_TOKEN: upon entering this state, the binding is informed -/// that the session wants an access token. The session is now waiting for the -/// binding to provide the token. -/// From: INACTIVE -/// To: -/// * ACTIVE: when the binding successfully refreshes the token -/// * INACTIVE: if asked to log out, or if asked to close and the stop policy -/// is Immediate. -/// * DYING: if asked to close and the stop policy is AfterChangesUploaded -/// * ERROR: if a fatal error occurs -/// -/// ACTIVE: the session is connected to the Realm Object Server and is actively -/// transferring data. -/// From: WAITING_FOR_ACCESS_TOKEN, DYING -/// To: -/// * WAITING_FOR_ACCESS_TOKEN: if the session is informed (through the error -/// handler) that the token expired -/// * INACTIVE: if asked to log out, or if asked to close and the stop policy -/// is Immediate. -/// * DYING: if asked to close and the stop policy is AfterChangesUploaded -/// * ERROR: if a fatal error occurs -/// -/// DYING: the session is performing clean-up work in preparation to be destroyed. -/// From: ACTIVE -/// To: -/// * INACTIVE: when the clean-up work completes, if the session wasn't -/// revived, or if explicitly asked to log out before the -/// clean-up work begins -/// * ACTIVE: if the session is revived -/// * ERROR: if a fatal error occurs -/// -/// INACTIVE: the user owning this session has logged out, the `sync::Session` -/// owned by this session is destroyed, and the session is quiescent. -/// From: initial, WAITING_FOR_ACCESS_TOKEN, ACTIVE, DYING -/// To: -/// * WAITING_FOR_ACCESS_TOKEN: if the session is revived -/// * ERROR: if a fatal error occurs -/// -/// ERROR: a non-recoverable error has occurred, and this session is semantically -/// invalid. The binding must create a new session with a different configuration. -/// From: WAITING_FOR_ACCESS_TOKEN, ACTIVE, DYING, INACTIVE -/// To: -/// * (none, this is a terminal state) -/// -struct SyncSession::State { - virtual ~State() { } - - virtual void enter_state(std::unique_lock&, SyncSession&) const { } - - virtual void refresh_access_token(std::unique_lock&, - SyncSession&, const std::string&, - const util::Optional&) const { } - - virtual void bind_with_admin_token(std::unique_lock&, - SyncSession&, const std::string&, const std::string&) const { } - - /// Returns true iff the lock is still locked when the method returns. - virtual bool access_token_expired(std::unique_lock&, SyncSession&) const { return true; } - - virtual void nonsync_transact_notify(std::unique_lock&, SyncSession&, sync::Session::version_type) const { } - - virtual bool revive_if_needed(std::unique_lock&, SyncSession&) const { return false; } - - virtual void log_out(std::unique_lock&, SyncSession&) const { } - - virtual void close_if_connecting(std::unique_lock&, SyncSession&) const { } - - virtual void close(std::unique_lock&, SyncSession&) const { } - - static const State& waiting_for_access_token; - static const State& active; - static const State& dying; - static const State& inactive; - static const State& error; -}; - -struct sync_session_states::WaitingForAccessToken : public SyncSession::State { - void enter_state(std::unique_lock&, SyncSession& session) const override - { - session.m_deferred_close = false; - } - - void refresh_access_token(std::unique_lock& lock, SyncSession& session, - const std::string& access_token, - const util::Optional& server_url) const override - { - // Since the sync session was previously unbound, it's safe to do this from the - // calling thread. - if (!session.m_server_url) { - session.m_server_url = std::move(server_url); - } - session.m_session->bind(*session.m_server_url, std::move(access_token)); - if (session.m_deferred_commit_notification) { - session.m_session->nonsync_transact_notify(*session.m_deferred_commit_notification); - session.m_deferred_commit_notification = util::none; - } - session.advance_state(lock, active); - if (session.m_deferred_close) { - session.m_deferred_close = false; - session.m_state->close(lock, session); - } - } - - void log_out(std::unique_lock& lock, SyncSession& session) const override - { - session.advance_state(lock, inactive); - } - - void nonsync_transact_notify(std::unique_lock&, - SyncSession& session, - sync::Session::version_type version) const override - { - // Notify at first available opportunity. - session.m_deferred_commit_notification = version; - } - - void close_if_connecting(std::unique_lock& lock, SyncSession& session) const override - { - // Ignore the sync configuration's stop policy as we're not yet connected. - session.advance_state(lock, inactive); - } - - void close(std::unique_lock&, SyncSession& session) const override - { - session.m_deferred_close = true; - } -}; - -struct sync_session_states::Active : public SyncSession::State { - void refresh_access_token(std::unique_lock&, SyncSession& session, - const std::string& access_token, - const util::Optional&) const override - { - session.m_session->refresh(std::move(access_token)); - } - - bool access_token_expired(std::unique_lock& lock, SyncSession& session) const override - { - session.advance_state(lock, waiting_for_access_token); - std::shared_ptr session_ptr = session.shared_from_this(); - lock.unlock(); - session.m_config.bind_session_handler(session_ptr->m_realm_path, session_ptr->m_config, std::move(session_ptr)); - return false; - } - - void log_out(std::unique_lock& lock, SyncSession& session) const override - { - session.advance_state(lock, inactive); - } - - void nonsync_transact_notify(std::unique_lock&, SyncSession& session, - sync::Session::version_type version) const override - { - // Fully ready sync session, notify immediately. - session.m_session->nonsync_transact_notify(version); - } - - void close(std::unique_lock& lock, SyncSession& session) const override - { - switch (session.m_config.stop_policy) { - case SyncSessionStopPolicy::Immediately: - session.advance_state(lock, inactive); - break; - case SyncSessionStopPolicy::LiveIndefinitely: - // Don't do anything; session lives forever. - break; - case SyncSessionStopPolicy::AfterChangesUploaded: - // Wait for all pending changes to upload. - session.advance_state(lock, dying); - break; - } - } -}; - -struct sync_session_states::Dying : public SyncSession::State { - void enter_state(std::unique_lock&, SyncSession& session) const override - { - size_t current_death_count = ++session.m_death_count; - session.m_session->async_wait_for_upload_completion([session=&session, current_death_count](std::error_code) { - std::unique_lock lock(session->m_state_mutex); - if (session->m_state == &State::dying && session->m_death_count == current_death_count) { - session->advance_state(lock, inactive); - } - }); - } - - bool revive_if_needed(std::unique_lock& lock, SyncSession& session) const override - { - // Revive. - session.advance_state(lock, active); - return false; - } - - void log_out(std::unique_lock& lock, SyncSession& session) const override - { - session.advance_state(lock, inactive); - } -}; - -struct sync_session_states::Inactive : public SyncSession::State { - void enter_state(std::unique_lock& lock, SyncSession& session) const override - { - session.m_session = nullptr; - session.m_server_url = util::none; - session.unregister(lock); - } - - void bind_with_admin_token(std::unique_lock& lock, SyncSession& session, - const std::string& admin_token, - const std::string& server_url) const override - { - session.create_sync_session(); - session.advance_state(lock, waiting_for_access_token); - session.m_state->refresh_access_token(lock, session, admin_token, server_url); - } - - bool revive_if_needed(std::unique_lock& lock, SyncSession& session) const override - { - // Revive. - session.create_sync_session(); - session.advance_state(lock, waiting_for_access_token); - return true; - } -}; - -struct sync_session_states::Error : public SyncSession::State { - void enter_state(std::unique_lock&, SyncSession& session) const override - { - session.m_session = nullptr; - session.m_config = { nullptr, "", SyncSessionStopPolicy::Immediately, nullptr }; - } - - // Everything else is a no-op when in the error state. -}; - - -const SyncSession::State& SyncSession::State::waiting_for_access_token = WaitingForAccessToken(); -const SyncSession::State& SyncSession::State::active = Active(); -const SyncSession::State& SyncSession::State::dying = Dying(); -const SyncSession::State& SyncSession::State::inactive = Inactive(); -const SyncSession::State& SyncSession::State::error = Error(); - - -SyncSession::SyncSession(SyncClient& client, std::string realm_path, SyncConfig config) -: m_state(&State::inactive) -, m_config(std::move(config)) -, m_realm_path(std::move(realm_path)) -, m_client(client) { } - -void SyncSession::create_sync_session() -{ - REALM_ASSERT(!m_session); - m_session = std::make_unique(m_client.client, m_realm_path); - - // Set up the wrapped handler - std::weak_ptr weak_self = shared_from_this(); - auto wrapped_handler = [this, weak_self](int error_code, std::string message) { - auto self = weak_self.lock(); - if (!self) { - // An error was delivered after the session it relates to was destroyed. There's nothing useful - // we can do with it. - return; - } - - using ProtocolError = realm::sync::ProtocolError; - - SyncSessionError error_type = SyncSessionError::Debug; - // Precondition: error_code is a valid realm::sync::Error raw value. - ProtocolError strong_code = static_cast(error_code); - - switch (strong_code) { - // Client errors; all ignored (for now) - case ProtocolError::invalid_error: - case ProtocolError::connection_closed: - case ProtocolError::other_error: - case ProtocolError::unknown_message: - case ProtocolError::bad_syntax: - case ProtocolError::limits_exceeded: - case ProtocolError::wrong_protocol_version: - case ProtocolError::bad_session_ident: - case ProtocolError::reuse_of_session_ident: - case ProtocolError::bound_in_other_session: - case ProtocolError::bad_message_order: - return; - // Session errors - case ProtocolError::disabled_session: - case ProtocolError::session_closed: - case ProtocolError::other_session_error: - // The binding doesn't need to be aware of these because they are strictly informational, and do not - // represent actual errors. - return; - case ProtocolError::token_expired: { - std::unique_lock lock(m_state_mutex); - // This isn't an error from the binding's point of view. If we're connected we'll - // simply ask the binding to log in again. - m_state->access_token_expired(lock, *this); - return; - } - case ProtocolError::bad_authentication: { - std::shared_ptr user_to_invalidate; - { - std::unique_lock lock(m_state_mutex); - error_type = SyncSessionError::UserFatal; - user_to_invalidate = user(); - advance_state(lock, State::error); - } - if (user_to_invalidate) - user_to_invalidate->invalidate(); - break; - } - case ProtocolError::illegal_realm_path: - case ProtocolError::no_such_realm: - case ProtocolError::bad_server_file_ident: - case ProtocolError::diverging_histories: - case ProtocolError::bad_changeset: { - std::unique_lock lock(m_state_mutex); - error_type = SyncSessionError::SessionFatal; - advance_state(lock, State::error); - break; - } - case ProtocolError::permission_denied: - error_type = SyncSessionError::AccessDenied; - break; - case ProtocolError::bad_client_file_ident: - case ProtocolError::bad_server_version: - case ProtocolError::bad_client_version: - error_type = SyncSessionError::Debug; - break; - } - if (m_error_handler) { - m_error_handler(std::move(self), error_code, message, error_type); - } - }; - m_session->set_error_handler(std::move(wrapped_handler)); - - // Set up the wrapped sync transact callback - auto wrapped_callback = [this, weak_self](VersionID old_version, VersionID new_version) { - if (auto self = weak_self.lock()) { - if (m_sync_transact_callback) { - m_sync_transact_callback(old_version, new_version); - } - } - }; - m_session->set_sync_transact_callback(std::move(wrapped_callback)); -} - -void SyncSession::set_sync_transact_callback(std::function callback) -{ - m_sync_transact_callback = std::move(callback); -} - -void SyncSession::set_error_handler(std::function handler) -{ - m_error_handler = std::move(handler); -} - -void SyncSession::advance_state(std::unique_lock& lock, const State& state) -{ - REALM_ASSERT(lock.owns_lock()); - REALM_ASSERT(&state != m_state); - m_state = &state; - m_state->enter_state(lock, *this); -} - -void SyncSession::nonsync_transact_notify(sync::Session::version_type version) -{ - std::unique_lock lock(m_state_mutex); - m_state->nonsync_transact_notify(lock, *this, version); -} - -void SyncSession::revive_if_needed(std::shared_ptr session) -{ - REALM_ASSERT(session); - util::Optional&> handler; - { - std::unique_lock lock(session->m_state_mutex); - if (session->m_state->revive_if_needed(lock, *session)) { - handler = session->m_config.bind_session_handler; - } - } - if (handler) { - handler.value()(session->m_realm_path, session->m_config, session); - } -} - -void SyncSession::log_out() -{ - std::unique_lock lock(m_state_mutex); - m_state->log_out(lock, *this); -} - -void SyncSession::close() -{ - std::unique_lock lock(m_state_mutex); - m_state->close(lock, *this); -} - -void SyncSession::close_if_connecting() -{ - std::unique_lock lock(m_state_mutex); - m_state->close_if_connecting(lock, *this); -} - -void SyncSession::unregister(std::unique_lock& lock) -{ - REALM_ASSERT(lock.owns_lock()); - REALM_ASSERT(m_state == &State::inactive); // Must stop an active session before unregistering. - - lock.unlock(); - SyncManager::shared().unregister_session(m_realm_path); -} - -bool SyncSession::can_wait_for_network_completion() const -{ - return m_state == &State::active || m_state == &State::dying; -} - -bool SyncSession::wait_for_upload_completion(std::function callback) -{ - std::unique_lock lock(m_state_mutex); - // FIXME: instead of dropping the callback if we haven't yet `bind()`ed, - // save it and register it when the session `bind()`s. - if (can_wait_for_network_completion()) { - REALM_ASSERT(m_session); - m_session->async_wait_for_upload_completion(std::move(callback)); - return true; - } - return false; -} - -bool SyncSession::wait_for_download_completion(std::function callback) -{ - std::unique_lock lock(m_state_mutex); - // FIXME: instead of dropping the callback if we haven't yet `bind()`ed, - // save it and register it when the session `bind()`s. - if (can_wait_for_network_completion()) { - REALM_ASSERT(m_session); - m_session->async_wait_for_download_completion(std::move(callback)); - return true; - } - return false; -} - -bool SyncSession::wait_for_upload_completion_blocking() -{ - std::unique_lock lock(m_state_mutex); - if (can_wait_for_network_completion()) { - REALM_ASSERT(m_session); - m_session->wait_for_upload_complete_or_client_stopped(); - return true; - } - return false; -} - -void SyncSession::refresh_access_token(std::string access_token, util::Optional server_url) -{ - std::unique_lock lock(m_state_mutex); - if (!m_server_url && !server_url) { - // The first time this method is called, the server URL must be provided. - return; - } - m_state->refresh_access_token(lock, *this, access_token, server_url); -} - -void SyncSession::bind_with_admin_token(std::string admin_token, std::string server_url) -{ - std::unique_lock lock(m_state_mutex); - m_state->bind_with_admin_token(lock, *this, admin_token, server_url); -} - -SyncSession::PublicState SyncSession::state() const -{ - std::unique_lock lock(m_state_mutex); - if (m_state == &State::waiting_for_access_token) { - return PublicState::WaitingForAccessToken; - } else if (m_state == &State::active) { - return PublicState::Active; - } else if (m_state == &State::dying) { - return PublicState::Dying; - } else if (m_state == &State::inactive) { - return PublicState::Inactive; - } else if (m_state == &State::error) { - return PublicState::Error; - } - REALM_UNREACHABLE(); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp deleted file mode 100644 index c5d8c71..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp +++ /dev/null @@ -1,195 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "sync/sync_user.hpp" - -#include "sync/impl/sync_metadata.hpp" -#include "sync/sync_manager.hpp" -#include "sync/sync_session.hpp" - -namespace realm { - -SyncUser::SyncUser(std::string refresh_token, - std::string identity, - util::Optional server_url, - bool is_admin) -: m_state(State::Active) -, m_server_url(server_url.value_or("")) -, m_is_admin(is_admin) -, m_refresh_token(std::move(refresh_token)) -, m_identity(std::move(identity)) -{ - if (!is_admin) { - SyncManager::shared().perform_metadata_update([this, server_url=std::move(server_url)](const auto& manager) { - auto metadata = SyncUserMetadata(manager, m_identity); - metadata.set_state(server_url, m_refresh_token); - }); - } -} - -std::vector> SyncUser::all_sessions() -{ - std::lock_guard lock(m_mutex); - std::vector> sessions; - if (m_state == State::Error) { - return sessions; - } - for (auto it = m_sessions.begin(); it != m_sessions.end();) { - if (auto ptr_to_session = it->second.lock()) { - if (!ptr_to_session->is_in_error_state()) { - sessions.emplace_back(std::move(ptr_to_session)); - it++; - continue; - } - } - // This session is bad, destroy it. - it = m_sessions.erase(it); - } - return sessions; -} - -std::shared_ptr SyncUser::session_for_on_disk_path(const std::string& path) -{ - std::lock_guard lock(m_mutex); - if (m_state == State::Error) { - return nullptr; - } - auto it = m_sessions.find(path); - if (it == m_sessions.end()) { - return nullptr; - } - auto locked = it->second.lock(); - if (!locked) { - // Remove the session from the map, because it has fatally errored out or the entry is invalid. - m_sessions.erase(it); - } - return locked; -} - -void SyncUser::update_refresh_token(std::string token) -{ - std::vector> sessions_to_revive; - { - std::unique_lock lock(m_mutex); - switch (m_state) { - case State::Error: - return; - case State::Active: - m_refresh_token = token; - break; - case State::LoggedOut: { - sessions_to_revive.reserve(m_waiting_sessions.size()); - m_refresh_token = token; - m_state = State::Active; - for (auto& pair : m_waiting_sessions) { - if (auto ptr = pair.second.lock()) { - m_sessions[pair.first] = ptr; - sessions_to_revive.emplace_back(std::move(ptr)); - } - } - m_waiting_sessions.clear(); - break; - } - } - // Update persistent user metadata. - if (!m_is_admin) { - SyncManager::shared().perform_metadata_update([=](const auto& manager) { - auto metadata = SyncUserMetadata(manager, m_identity); - metadata.set_state(m_server_url, token); - }); - } - } - // (Re)activate all pending sessions. - // Note that we do this after releasing the lock, since the session may - // need to access protected User state in the process of binding itself. - for (auto& session : sessions_to_revive) { - SyncSession::revive_if_needed(session); - } -} - -void SyncUser::log_out() -{ - if (m_is_admin) { - // Admin users cannot be logged out. - return; - } - std::lock_guard lock(m_mutex); - if (m_state == State::LoggedOut) { - return; - } - m_state = State::LoggedOut; - // Move all active sessions into the waiting sessions pool. If the user is - // logged back in, they will automatically be reactivated. - for (auto& pair : m_sessions) { - if (auto ptr = pair.second.lock()) { - ptr->log_out(); - m_waiting_sessions[pair.first] = ptr; - } - } - m_sessions.clear(); - // Mark the user as 'dead' in the persisted metadata Realm. - if (!m_is_admin) { - SyncManager::shared().perform_metadata_update([=](const auto& manager) { - auto metadata = SyncUserMetadata(manager, m_identity, false); - metadata.mark_for_removal(); - }); - } -} - -void SyncUser::invalidate() -{ - std::lock_guard lock(m_mutex); - m_state = State::Error; -} - -std::string SyncUser::refresh_token() const -{ - std::lock_guard lock(m_mutex); - return m_refresh_token; -} - -SyncUser::State SyncUser::state() const -{ - std::lock_guard lock(m_mutex); - return m_state; -} - -void SyncUser::register_session(std::shared_ptr session) -{ - const std::string& path = session->path(); - std::unique_lock lock(m_mutex); - switch (m_state) { - case State::Active: - // Immediately ask the session to come online. - m_sessions[path] = session; - if (m_is_admin) { - session->bind_with_admin_token(m_refresh_token, session->config().realm_url); - } else { - lock.unlock(); - SyncSession::revive_if_needed(std::move(session)); - } - break; - case State::LoggedOut: - m_waiting_sessions[path] = session; - break; - case State::Error: - break; - } -} - -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/thread_confined.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/thread_confined.cpp deleted file mode 100644 index 0db0d57..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/thread_confined.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "thread_confined.hpp" - -#include "impl/handover.hpp" - -using namespace realm; - -AnyThreadConfined::AnyThreadConfined(const AnyThreadConfined& thread_confined) -{ - switch (thread_confined.m_type) { - case Type::Object: - new (&m_object) Object(thread_confined.m_object); - break; - - case Type::List: - new (&m_list) List(thread_confined.m_list); - break; - - case Type::Results: - new (&m_results) Results(thread_confined.m_results); - break; - } - new (&m_type) Type(thread_confined.m_type); -} - -AnyThreadConfined& AnyThreadConfined::operator=(const AnyThreadConfined& thread_confined) -{ - this->~AnyThreadConfined(); - new (this) AnyThreadConfined(thread_confined); - return *this; -} - -AnyThreadConfined::AnyThreadConfined(AnyThreadConfined&& thread_confined) -{ - switch (thread_confined.m_type) { - case Type::Object: - new (&m_object) Object(std::move(thread_confined.m_object)); - break; - - case Type::List: - new (&m_list) List(std::move(thread_confined.m_list)); - break; - - case Type::Results: - new (&m_results) Results(std::move(thread_confined.m_results)); - break; - } - new (&m_type) Type(std::move(thread_confined.m_type)); -} - -AnyThreadConfined& AnyThreadConfined::operator=(AnyThreadConfined&& thread_confined) -{ - this->~AnyThreadConfined(); - new (this) AnyThreadConfined(std::move(thread_confined)); - return *this; -} - -AnyThreadConfined::~AnyThreadConfined() -{ - switch (m_type) { - case Type::Object: - m_object.~Object(); - break; - - case Type::List: - m_list.~List(); - break; - - case Type::Results: - m_results.~Results(); - break; - } -} - -SharedRealm AnyThreadConfined::get_realm() const -{ - switch (m_type) { - case Type::Object: - return m_object.realm(); - - case Type::List: - return m_list.get_realm(); - - case Type::Results: - return m_results.get_realm(); - } - REALM_UNREACHABLE(); -} - -_impl::AnyHandover AnyThreadConfined::export_for_handover() const -{ - SharedGroup& shared_group = Realm::Internal::get_shared_group(*get_realm()); - switch (m_type) { - case AnyThreadConfined::Type::Object: - return _impl::AnyHandover(shared_group.export_for_handover(m_object.row()), - m_object.get_object_schema().name); - - case AnyThreadConfined::Type::List: - return _impl::AnyHandover(shared_group.export_linkview_for_handover(m_list.m_link_view)); - - case AnyThreadConfined::Type::Results: { - SortDescriptor::HandoverPatch sort_order; - SortDescriptor::generate_patch(m_results.get_sort(), sort_order); - return _impl::AnyHandover(shared_group.export_for_handover(m_results.get_query(), ConstSourcePayload::Copy), - std::move(sort_order)); - } - } - REALM_UNREACHABLE(); -} diff --git a/Example/Pods/Realm/Realm/ObjectStore/src/util/format.cpp b/Example/Pods/Realm/Realm/ObjectStore/src/util/format.cpp deleted file mode 100644 index 4103c8d..0000000 --- a/Example/Pods/Realm/Realm/ObjectStore/src/util/format.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#include "util/format.hpp" - -#include - -#include -#include - -namespace realm { namespace _impl { -Printable::Printable(StringData value) : m_type(Type::String), m_string(value.data()) { } - -void Printable::print(std::ostream& out) const -{ - switch (m_type) { - case Printable::Type::Bool: - out << (m_uint ? "true" : "false"); - break; - case Printable::Type::Uint: - out << m_uint; - break; - case Printable::Type::Int: - out << m_int; - break; - case Printable::Type::String: - out << m_string; - break; - } -} - -std::string format(const char* fmt, std::initializer_list values) -{ - std::stringstream ss; - while (*fmt) { - auto next = strchr(fmt, '%'); - - // emit the rest of the format string if there are no more percents - if (!next) { - ss << fmt; - break; - } - - // emit everything up to the next percent - ss.write(fmt, next - fmt); - ++next; - REALM_ASSERT(*next); - - // %% produces a single escaped % - if (*next == '%') { - ss << '%'; - fmt = next + 1; - continue; - } - REALM_ASSERT(isdigit(*next)); - - // The const_cast is safe because stroul does not actually modify - // the pointed-to string, but it lacks a const overload - auto index = strtoul(next, const_cast(&fmt), 10) - 1; - REALM_ASSERT(index < values.size()); - (values.begin() + index)->print(ss); - } - return ss.str(); -} - -} // namespace _impl -} // namespace realm diff --git a/Example/Pods/Realm/Realm/RLMAccessor.mm b/Example/Pods/Realm/Realm/RLMAccessor.mm deleted file mode 100644 index 724ccf0..0000000 --- a/Example/Pods/Realm/Realm/RLMAccessor.mm +++ /dev/null @@ -1,801 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMAccessor.h" - -#import "RLMArray_Private.hpp" -#import "RLMListBase.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObject_Private.hpp" -#import "RLMObservation.hpp" -#import "RLMProperty_Private.h" -#import "RLMRealm_Private.hpp" -#import "RLMResults_Private.h" -#import "RLMSchema_Private.h" -#import "RLMUtil.hpp" -#import "results.hpp" -#import "property.hpp" - -#import -#import - -typedef NS_ENUM(char, RLMAccessorCode) { - RLMAccessorCodeByte, - RLMAccessorCodeShort, - RLMAccessorCodeInt, - RLMAccessorCodeLong, - RLMAccessorCodeLongLong, - RLMAccessorCodeFloat, - RLMAccessorCodeDouble, - RLMAccessorCodeBool, - RLMAccessorCodeString, - RLMAccessorCodeDate, - RLMAccessorCodeData, - RLMAccessorCodeLink, - RLMAccessorCodeArray, - RLMAccessorCodeLinkingObjects, - RLMAccessorCodeAny, - - RLMAccessorCodeIntObject, - RLMAccessorCodeFloatObject, - RLMAccessorCodeDoubleObject, - RLMAccessorCodeBoolObject, -}; - -template -static T get(__unsafe_unretained RLMObjectBase *const obj, NSUInteger index) { - RLMVerifyAttached(obj); - return obj->_row.get_table()->get(obj->_info->objectSchema->persisted_properties[index].table_column, obj->_row.get_index()); -} - -template -static NSNumber *getBoxed(__unsafe_unretained RLMObjectBase *const obj, NSUInteger index) { - RLMVerifyAttached(obj); - auto col = obj->_info->objectSchema->persisted_properties[index].table_column; - if (obj->_row.is_null(col)) { - return nil; - } - return @(obj->_row.get_table()->get(col, obj->_row.get_index())); -} - - -// long getter/setter -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, long long val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - obj->_row.get_table()->set_int(colIndex, obj->_row.get_index(), val, setDefault); -} - -// float getter/setter -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, float val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - obj->_row.get_table()->set_float(colIndex, obj->_row.get_index(), val, setDefault); -} - -// double getter/setter -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, double val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - obj->_row.get_table()->set_double(colIndex, obj->_row.get_index(), val, setDefault); -} - -// bool getter/setter -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, BOOL val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - obj->_row.get_table()->set_bool(colIndex, obj->_row.get_index(), val, setDefault); -} - -// string getter/setter -static inline NSString *RLMGetString(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) { - return RLMStringDataToNSString(get(obj, colIndex)); -} -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSString *const val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - try { - obj->_row.get_table()->set_string(colIndex, obj->_row.get_index(), RLMStringDataWithNSString(val), setDefault); - } - catch (std::exception const& e) { - @throw RLMException(e); - } -} - -// date getter/setter -static inline NSDate *RLMGetDate(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) { - return RLMTimestampToNSDate(get(obj, colIndex)); -} -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSDate *const date, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - if (date) { - obj->_row.get_table()->set_timestamp(colIndex, obj->_row.get_index(), RLMTimestampForNSDate(date), setDefault); - } - else { - obj->_row.set_null(colIndex); - } -} - -// data getter/setter -static inline NSData *RLMGetData(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) { - return RLMBinaryDataToNSData(get(obj, colIndex)); -} -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, __unsafe_unretained NSData *const data, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - try { - obj->_row.get_table()->set_binary(colIndex, obj->_row.get_index(), RLMBinaryDataForNSData(data), setDefault); - } - catch (std::exception const& e) { - @throw RLMException(e); - } -} - -static inline RLMObjectBase *RLMGetLinkedObjectForValue(__unsafe_unretained RLMRealm *const realm, - __unsafe_unretained NSString *const className, - __unsafe_unretained id const value, - RLMCreationOptions creationOptions) NS_RETURNS_RETAINED; -static inline RLMObjectBase *RLMGetLinkedObjectForValue(__unsafe_unretained RLMRealm *const realm, - __unsafe_unretained NSString *const className, - __unsafe_unretained id const value, - RLMCreationOptions creationOptions) { - RLMObjectBase *link = RLMDynamicCast(value); - if (!link || ![link->_objectSchema.className isEqualToString:className]) { - // create from non-rlmobject - return RLMCreateObjectInRealmWithValue(realm, className, value, creationOptions & RLMCreationOptionsCreateOrUpdate); - } - - if (link.isInvalidated) { - @throw RLMException(@"Adding a deleted or invalidated object to a Realm is not permitted"); - } - - if (link->_realm == realm) { - return link; - } - - if (creationOptions & RLMCreationOptionsPromoteUnmanaged) { - if (!link->_realm) { - RLMAddObjectToRealm(link, realm, creationOptions & RLMCreationOptionsCreateOrUpdate); - return link; - } - @throw RLMException(@"Can not add objects from a different Realm"); - } - - // copy from another realm or copy from unmanaged - return RLMCreateObjectInRealmWithValue(realm, className, link, creationOptions & RLMCreationOptionsCreateOrUpdate); -} - -// link getter/setter -static inline RLMObjectBase *RLMGetLink(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) { - RLMVerifyAttached(obj); - auto col = obj->_info->objectSchema->persisted_properties[colIndex].table_column; - - if (obj->_row.is_null_link(col)) { - return nil; - } - NSUInteger index = obj->_row.get_link(col); - return RLMCreateObjectAccessor(obj->_realm, obj->_info->linkTargetType(colIndex), index); -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained RLMObjectBase *const val, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - if (!val) { - obj->_row.nullify_link(colIndex); - return; - } - - RLMObjectBase *link = RLMGetLinkedObjectForValue(obj->_realm, val->_objectSchema.className, - val, RLMCreationOptionsPromoteUnmanaged); - - // make sure it is the correct type - if (link->_row.get_table() != obj->_row.get_table()->get_link_target(colIndex)) { - @throw RLMException(@"Can't set object of type '%@' to property of type '%@'", - val->_objectSchema.className, - obj->_info->propertyForTableColumn(colIndex).objectClassName); - } - obj->_row.get_table()->set_link(colIndex, obj->_row.get_index(), link->_row.get_index(), setDefault); -} - -// array getter/setter -static inline RLMArray *RLMGetArray(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex) { - RLMVerifyAttached(obj); - auto prop = obj->_info->rlmObjectSchema.properties[colIndex]; - return [[RLMArrayLinkView alloc] initWithParent:obj property:prop]; -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained id const array, __unused bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - realm::LinkViewRef linkView = obj->_row.get_linklist(colIndex); - // remove all old - // FIXME: make sure delete rules don't purge objects - linkView->clear(); - for (RLMObjectBase *link in array) { - RLMObjectBase * addedLink = RLMGetLinkedObjectForValue(obj->_realm, link->_objectSchema.className, link, RLMCreationOptionsPromoteUnmanaged); - linkView->add(addedLink->_row.get_index()); - } -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained NSNumber *const intObject, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - if (intObject) { - obj->_row.get_table()->set_int(colIndex, obj->_row.get_index(), intObject.longLongValue, setDefault); - } - else { - obj->_row.get_table()->set_null(colIndex, obj->_row.get_index(), setDefault); - } -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained NSNumber *const floatObject, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - if (floatObject) { - obj->_row.get_table()->set_float(colIndex, obj->_row.get_index(), floatObject.floatValue, setDefault); - } - else { - obj->_row.get_table()->set_null(colIndex, obj->_row.get_index(), setDefault); - } -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained NSNumber *const doubleObject, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - if (doubleObject) { - obj->_row.get_table()->set_double(colIndex, obj->_row.get_index(), doubleObject.doubleValue, setDefault); - } - else { - obj->_row.get_table()->set_null(colIndex, obj->_row.get_index(), setDefault); - } -} - -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger colIndex, - __unsafe_unretained NSNumber *const boolObject, bool setDefault) { - RLMVerifyInWriteTransaction(obj); - - if (boolObject) { - obj->_row.get_table()->set_bool(colIndex, obj->_row.get_index(), boolObject.boolValue, setDefault); - } - else { - obj->_row.get_table()->set_null(colIndex, obj->_row.get_index(), setDefault); - } -} - -static inline RLMLinkingObjects *RLMGetLinkingObjects(__unsafe_unretained RLMObjectBase *const obj, - __unsafe_unretained RLMProperty *const property) { - auto& objectInfo = obj->_realm->_info[property.objectClassName]; - auto linkingProperty = objectInfo.objectSchema->property_for_name(property.linkOriginPropertyName.UTF8String); - auto backlinkView = obj->_row.get_table()->get_backlink_view(obj->_row.get_index(), objectInfo.table(), linkingProperty->table_column); - realm::Results results(obj->_realm->_realm, std::move(backlinkView)); - return [RLMLinkingObjects resultsWithObjectInfo:objectInfo results:std::move(results)]; -} - -// any getter/setter -static inline id RLMGetAnyProperty(__unsafe_unretained RLMObjectBase *const obj, NSUInteger col_ndx) { - RLMVerifyAttached(obj); - return RLMMixedToObjc(obj->_row.get_mixed(col_ndx)); -} -static inline void RLMSetValue(__unsafe_unretained RLMObjectBase *const obj, NSUInteger, __unsafe_unretained id, bool) { - RLMVerifyInWriteTransaction(obj); - @throw RLMException(@"Modifying Mixed properties is not supported"); -} - -// dynamic getter with column closure -static IMP RLMAccessorGetter(RLMProperty *prop, RLMAccessorCode accessorCode) { - NSUInteger index = prop.index; - switch (accessorCode) { - case RLMAccessorCodeByte: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return (char)get(obj, index); - }); - case RLMAccessorCodeShort: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return (short)get(obj, index); - }); - case RLMAccessorCodeInt: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return (int)get(obj, index); - }); - case RLMAccessorCodeLongLong: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return get(obj, index); - }); - case RLMAccessorCodeLong: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return (long)get(obj, index); - }); - case RLMAccessorCodeFloat: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return get(obj, index); - }); - case RLMAccessorCodeDouble: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return get(obj, index); - }); - case RLMAccessorCodeBool: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return get(obj, index); - }); - case RLMAccessorCodeString: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetString(obj, index); - }); - case RLMAccessorCodeDate: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetDate(obj, index); - }); - case RLMAccessorCodeData: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetData(obj, index); - }); - case RLMAccessorCodeLink: - return imp_implementationWithBlock(^id(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetLink(obj, index); - }); - case RLMAccessorCodeArray: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetArray(obj, index); - }); - case RLMAccessorCodeAny: - @throw RLMException(@"Cannot create accessor class for schema with Mixed properties"); - case RLMAccessorCodeIntObject: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return getBoxed(obj, index); - }); - case RLMAccessorCodeFloatObject: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return getBoxed(obj, index); - }); - case RLMAccessorCodeDoubleObject: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return getBoxed(obj, index); - }); - case RLMAccessorCodeBoolObject: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return getBoxed(obj, index); - }); - case RLMAccessorCodeLinkingObjects: - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj) { - return RLMGetLinkingObjects(obj, prop); - }); - } -} - -template -static void RLMWrapSetter(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained NSString *const name, Function&& f) { - if (RLMObservationInfo *info = RLMGetObservationInfo(obj->_observationInfo, obj->_row.get_index(), *obj->_info)) { - info->willChange(name); - f(); - info->didChange(name); - } - else { - f(); - } -} - -template -static IMP RLMMakeSetter(RLMProperty *prop) { - NSUInteger index = prop.index; - NSString *name = prop.name; - if (prop.isPrimary) { - return imp_implementationWithBlock(^(__unused RLMObjectBase *obj, __unused ArgType val) { - @throw RLMException(@"Primary key can't be changed after an object is inserted."); - }); - } - return imp_implementationWithBlock(^(__unsafe_unretained RLMObjectBase *const obj, ArgType val) { - RLMWrapSetter(obj, name, [&] { - RLMSetValue(obj, obj->_info->objectSchema->persisted_properties[index].table_column, static_cast(val), false); - }); - }); -} - -// dynamic setter with column closure -static IMP RLMAccessorSetter(RLMProperty *prop, RLMAccessorCode accessorCode) { - switch (accessorCode) { - case RLMAccessorCodeByte: return RLMMakeSetter(prop); - case RLMAccessorCodeShort: return RLMMakeSetter(prop); - case RLMAccessorCodeInt: return RLMMakeSetter(prop); - case RLMAccessorCodeLong: return RLMMakeSetter(prop); - case RLMAccessorCodeLongLong: return RLMMakeSetter(prop); - case RLMAccessorCodeFloat: return RLMMakeSetter(prop); - case RLMAccessorCodeDouble: return RLMMakeSetter(prop); - case RLMAccessorCodeBool: return RLMMakeSetter(prop); - case RLMAccessorCodeString: return RLMMakeSetter(prop); - case RLMAccessorCodeDate: return RLMMakeSetter(prop); - case RLMAccessorCodeData: return RLMMakeSetter(prop); - case RLMAccessorCodeLink: return RLMMakeSetter(prop); - case RLMAccessorCodeArray: return RLMMakeSetter(prop); - case RLMAccessorCodeAny: return RLMMakeSetter(prop); - case RLMAccessorCodeIntObject: return RLMMakeSetter *>(prop); - case RLMAccessorCodeFloatObject: return RLMMakeSetter *>(prop); - case RLMAccessorCodeDoubleObject: return RLMMakeSetter *>(prop); - case RLMAccessorCodeBoolObject: return RLMMakeSetter *>(prop); - case RLMAccessorCodeLinkingObjects: return nil; - } -} - -// call getter for superclass for property at colIndex -static id RLMSuperGet(RLMObjectBase *obj, NSString *propName) { - typedef id (*getter_type)(RLMObjectBase *, SEL); - RLMProperty *prop = obj->_objectSchema[propName]; - Class superClass = class_getSuperclass(obj.class); - getter_type superGetter = (getter_type)[superClass instanceMethodForSelector:prop.getterSel]; - return superGetter(obj, prop.getterSel); -} - -// call setter for superclass for property at colIndex -static void RLMSuperSet(RLMObjectBase *obj, NSString *propName, id val) { - typedef void (*setter_type)(RLMObjectBase *, SEL, RLMArray *ar); - RLMProperty *prop = obj->_objectSchema[propName]; - Class superClass = class_getSuperclass(obj.class); - setter_type superSetter = (setter_type)[superClass instanceMethodForSelector:prop.setterSel]; - superSetter(obj, prop.setterSel, val); -} - -// getter/setter for unmanaged object -static IMP RLMAccessorUnmanagedGetter(RLMProperty *prop, RLMAccessorCode accessorCode) { - // only override getters for RLMArray and linking objects properties - if (accessorCode == RLMAccessorCodeArray) { - NSString *objectClassName = prop.objectClassName; - NSString *propName = prop.name; - - return imp_implementationWithBlock(^(RLMObjectBase *obj) { - id val = RLMSuperGet(obj, propName); - if (!val) { - val = [[RLMArray alloc] initWithObjectClassName:objectClassName]; - RLMSuperSet(obj, propName, val); - } - return val; - }); - } - else if (accessorCode == RLMAccessorCodeLinkingObjects) { - return imp_implementationWithBlock(^(RLMObjectBase *){ - return [RLMResults emptyDetachedResults]; - }); - } - return nil; -} -static IMP RLMAccessorUnmanagedSetter(RLMProperty *prop, RLMAccessorCode accessorCode) { - // only override getters for RLMArray and linking objects properties - if (accessorCode == RLMAccessorCodeArray) { - NSString *propName = prop.name; - NSString *objectClassName = prop.objectClassName; - return imp_implementationWithBlock(^(RLMObjectBase *obj, id ar) { - // make copy when setting (as is the case for all other variants) - RLMArray *unmanagedAr = [[RLMArray alloc] initWithObjectClassName:objectClassName]; - [unmanagedAr addObjects:ar]; - RLMSuperSet(obj, propName, unmanagedAr); - }); - } - return nil; -} - -// macros/helpers to generate objc type strings for registering methods -#define GETTER_TYPES(C) C "@:" -#define SETTER_TYPES(C) "v@:" C - -// getter type strings -// NOTE: this typecode is really the the first charachter of the objc/runtime.h type -// the @ type maps to multiple core types (string, date, array, mixed, any which are id in objc) -static const char *getterTypeStringForObjcCode(char code) { - switch (code) { - case 's': return GETTER_TYPES("s"); - case 'i': return GETTER_TYPES("i"); - case 'l': return GETTER_TYPES("l"); - case 'q': return GETTER_TYPES("q"); - case 'f': return GETTER_TYPES("f"); - case 'd': return GETTER_TYPES("d"); - case 'B': return GETTER_TYPES("B"); - case 'c': return GETTER_TYPES("c"); - case '@': return GETTER_TYPES("@"); - default: @throw RLMException(@"Invalid accessor code"); - } -} - -// setter type strings -// NOTE: this typecode is really the the first charachter of the objc/runtime.h type -// the @ type maps to multiple core types (string, date, array, mixed, any which are id in objc) -static const char *setterTypeStringForObjcCode(char code) { - switch (code) { - case 's': return SETTER_TYPES("s"); - case 'i': return SETTER_TYPES("i"); - case 'l': return SETTER_TYPES("l"); - case 'q': return SETTER_TYPES("q"); - case 'f': return SETTER_TYPES("f"); - case 'd': return SETTER_TYPES("d"); - case 'B': return SETTER_TYPES("B"); - case 'c': return SETTER_TYPES("c"); - case '@': return SETTER_TYPES("@"); - default: @throw RLMException(@"Invalid accessor code"); - } -} - -// get accessor lookup code based on objc type and rlm type -static RLMAccessorCode accessorCodeForType(char objcTypeCode, RLMPropertyType rlmType) { - switch (objcTypeCode) { - case 't': return RLMAccessorCodeArray; - case '@': // custom accessors for strings and subtables - switch (rlmType) { // custom accessor codes for types that map to objc objects - case RLMPropertyTypeObject: return RLMAccessorCodeLink; - case RLMPropertyTypeString: return RLMAccessorCodeString; - case RLMPropertyTypeArray: return RLMAccessorCodeArray; - case RLMPropertyTypeDate: return RLMAccessorCodeDate; - case RLMPropertyTypeData: return RLMAccessorCodeData; - case RLMPropertyTypeAny: return RLMAccessorCodeAny; - - case RLMPropertyTypeBool: return RLMAccessorCodeBoolObject; - case RLMPropertyTypeDouble: return RLMAccessorCodeDoubleObject; - case RLMPropertyTypeFloat: return RLMAccessorCodeFloatObject; - case RLMPropertyTypeInt: return RLMAccessorCodeIntObject; - - case RLMPropertyTypeLinkingObjects: return RLMAccessorCodeLinkingObjects; - } - case 'c': - switch (rlmType) { - case RLMPropertyTypeInt: return RLMAccessorCodeByte; - case RLMPropertyTypeBool: return RLMAccessorCodeBool; - default: - @throw RLMException(@"Unexpected property type for Objective-C type code"); - } - case 'B': return RLMAccessorCodeBool; - case 's': return RLMAccessorCodeShort; - case 'i': return RLMAccessorCodeInt; - case 'l': return RLMAccessorCodeLong; - case 'q': return RLMAccessorCodeLongLong; - case 'f': return RLMAccessorCodeFloat; - case 'd': return RLMAccessorCodeDouble; - default: - @throw RLMException(@"Invalid type for objc typecode"); - } -} - -// implement the class method className on accessors to return the className of the -// base object -void RLMReplaceClassNameMethod(Class accessorClass, NSString *className) { - Class metaClass = object_getClass(accessorClass); - IMP imp = imp_implementationWithBlock(^(Class){ return className; }); - class_addMethod(metaClass, @selector(className), imp, "@@:"); -} - -// implement the shared schema method -void RLMReplaceSharedSchemaMethod(Class accessorClass, RLMObjectSchema *schema) { - Class metaClass = object_getClass(accessorClass); - IMP imp = imp_implementationWithBlock(^(Class cls) { - if (cls == accessorClass) { - return schema; - } - - // If we aren't being called directly on the class this was overriden - // for, the class is either a subclass which we haven't initialized yet, - // or it's a runtime-generated class which should use the parent's - // schema. We check for the latter by checking if the immediate - // descendent of the desired class is a class generated by us (there - // may be further subclasses not generated by us for things like KVO). - Class parent = class_getSuperclass(cls); - while (parent != accessorClass) { - cls = parent; - parent = class_getSuperclass(cls); - } - if (RLMIsGeneratedClass(cls)) { - return schema; - } - - return [RLMSchema sharedSchemaForClass:cls]; - }); - class_addMethod(metaClass, @selector(sharedSchema), imp, "@@:"); -} - -static NSMutableSet *s_generatedClasses = [NSMutableSet new]; -static void RLMMarkClassAsGenerated(Class cls) { - @synchronized (s_generatedClasses) { - [s_generatedClasses addObject:cls]; - } -} - -bool RLMIsGeneratedClass(Class cls) { - @synchronized (s_generatedClasses) { - return [s_generatedClasses containsObject:cls]; - } -} - -static Class RLMCreateAccessorClass(Class objectClass, - RLMObjectSchema *schema, - NSString *accessorClassPrefix, - IMP (*getterGetter)(RLMProperty *, RLMAccessorCode), - IMP (*setterGetter)(RLMProperty *, RLMAccessorCode)) { - // throw if no schema, prefix, or object class - if (!objectClass || !schema || !accessorClassPrefix) { - @throw RLMException(@"Missing arguments"); - } - if (!RLMIsObjectOrSubclass(objectClass)) { - @throw RLMException(@"objectClass must derive from RLMObject or Object"); - } - - // create and register proxy class which derives from object class - NSString *accessorClassName = [accessorClassPrefix stringByAppendingString:schema.className]; - Class accClass = objc_getClass(accessorClassName.UTF8String); - if (!accClass) { - accClass = objc_allocateClassPair(objectClass, accessorClassName.UTF8String, 0); - objc_registerClassPair(accClass); - } - - // override getters/setters for each propery - NSArray *allProperties = [schema.properties arrayByAddingObjectsFromArray:schema.computedProperties]; - for (RLMProperty *prop in allProperties) { - RLMAccessorCode accessorCode = accessorCodeForType(prop.objcType, prop.type); - if (prop.getterSel && getterGetter) { - IMP getterImp = getterGetter(prop, accessorCode); - if (getterImp) { - class_replaceMethod(accClass, prop.getterSel, getterImp, getterTypeStringForObjcCode(prop.objcType)); - } - } - if (prop.setterSel && setterGetter) { - IMP setterImp = setterGetter(prop, accessorCode); - if (setterImp) { - class_replaceMethod(accClass, prop.setterSel, setterImp, setterTypeStringForObjcCode(prop.objcType)); - } - } - } - - RLMMarkClassAsGenerated(accClass); - - return accClass; -} - -Class RLMAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema, NSString *prefix) { - return RLMCreateAccessorClass(objectClass, schema, prefix, RLMAccessorGetter, RLMAccessorSetter); -} - -Class RLMUnmanagedAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema) { - return RLMCreateAccessorClass(objectClass, schema, @"RLMUnmanaged_", - RLMAccessorUnmanagedGetter, RLMAccessorUnmanagedSetter); -} - -void RLMDynamicValidatedSet(RLMObjectBase *obj, NSString *propName, id val) { - RLMObjectSchema *schema = obj->_objectSchema; - RLMProperty *prop = schema[propName]; - if (!prop) { - @throw RLMException(@"Invalid property name '%@' for class '%@'.", propName, obj->_objectSchema.className); - } - if (prop.isPrimary) { - @throw RLMException(@"Primary key can't be changed to '%@' after an object is inserted.", val); - } - if (!RLMIsObjectValidForProperty(val, prop)) { - @throw RLMException(@"Invalid property value '%@' for property '%@' of class '%@'", val, propName, obj->_objectSchema.className); - } - - RLMDynamicSet(obj, prop, RLMCoerceToNil(val), RLMCreationOptionsPromoteUnmanaged); -} - -// Precondition: the property is not a primary key -void RLMDynamicSet(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained RLMProperty *const prop, - __unsafe_unretained id const val, RLMCreationOptions creationOptions) { - REALM_ASSERT_DEBUG(!prop.isPrimary); - bool setDefault = creationOptions & RLMCreationOptionsSetDefault; - - auto col = obj->_info->tableColumn(prop); - RLMWrapSetter(obj, prop.name, [&] { - switch (accessorCodeForType(prop.objcType, prop.type)) { - case RLMAccessorCodeByte: - case RLMAccessorCodeShort: - case RLMAccessorCodeInt: - case RLMAccessorCodeLong: - case RLMAccessorCodeLongLong: - RLMSetValue(obj, col, [val longLongValue], setDefault); - break; - case RLMAccessorCodeFloat: - RLMSetValue(obj, col, [val floatValue], setDefault); - break; - case RLMAccessorCodeDouble: - RLMSetValue(obj, col, [val doubleValue], setDefault); - break; - case RLMAccessorCodeBool: - RLMSetValue(obj, col, [val boolValue], setDefault); - break; - case RLMAccessorCodeIntObject: - RLMSetValue(obj, col, (NSNumber *)val, setDefault); - break; - case RLMAccessorCodeFloatObject: - RLMSetValue(obj, col, (NSNumber *)val, setDefault); - break; - case RLMAccessorCodeDoubleObject: - RLMSetValue(obj, col, (NSNumber *)val, setDefault); - break; - case RLMAccessorCodeBoolObject: - RLMSetValue(obj, col, (NSNumber *)val, setDefault); - break; - case RLMAccessorCodeString: - RLMSetValue(obj, col, (NSString *)val, setDefault); - break; - case RLMAccessorCodeDate: - RLMSetValue(obj, col, (NSDate *)val, setDefault); - break; - case RLMAccessorCodeData: - RLMSetValue(obj, col, (NSData *)val, setDefault); - break; - case RLMAccessorCodeLink: { - if (!val || val == NSNull.null) { - RLMSetValue(obj, col, (RLMObjectBase *)nil, setDefault); - } - else { - RLMSetValue(obj, col, RLMGetLinkedObjectForValue(obj->_realm, prop.objectClassName, val, creationOptions), setDefault); - } - break; - } - case RLMAccessorCodeArray: - if (!val || val == NSNull.null) { - RLMSetValue(obj, col, (id)nil, setDefault); - } - else { - id rawLinks = val; - NSMutableArray *links = [NSMutableArray array]; - for (id rawLink in rawLinks) { - [links addObject:RLMGetLinkedObjectForValue(obj->_realm, prop.objectClassName, rawLink, creationOptions)]; - } - RLMSetValue(obj, col, links, setDefault); - } - break; - case RLMAccessorCodeAny: - RLMSetValue(obj, col, val, setDefault); - break; - case RLMAccessorCodeLinkingObjects: - @throw RLMException(@"Linking objects properties are read-only"); - } - }); -} - -id RLMDynamicGet(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained RLMProperty *const prop) { - auto index = prop.index; - switch (accessorCodeForType(prop.objcType, prop.type)) { - case RLMAccessorCodeIntObject: - case RLMAccessorCodeByte: - case RLMAccessorCodeShort: - case RLMAccessorCodeInt: - case RLMAccessorCodeLong: - case RLMAccessorCodeLongLong: return getBoxed(obj, index); - case RLMAccessorCodeFloatObject: - case RLMAccessorCodeFloat: return getBoxed(obj, index); - case RLMAccessorCodeDoubleObject: - case RLMAccessorCodeDouble: return getBoxed(obj, index); - case RLMAccessorCodeBoolObject: - case RLMAccessorCodeBool: return getBoxed(obj, index); - case RLMAccessorCodeString: return RLMGetString(obj, index); - case RLMAccessorCodeDate: return RLMGetDate(obj, index); - case RLMAccessorCodeData: return RLMGetData(obj, index); - case RLMAccessorCodeLink: return RLMGetLink(obj, index); - case RLMAccessorCodeArray: return RLMGetArray(obj, index); - case RLMAccessorCodeAny: return RLMGetAnyProperty(obj, index); - case RLMAccessorCodeLinkingObjects: return RLMGetLinkingObjects(obj, prop); - } -} - -id RLMDynamicGetByName(__unsafe_unretained RLMObjectBase *const obj, __unsafe_unretained NSString *const propName, bool asList) { - RLMProperty *prop = obj->_objectSchema[propName]; - if (!prop) { - @throw RLMException(@"Invalid property name '%@' for class '%@'.", propName, obj->_objectSchema.className); - } - if (asList && prop.type == RLMPropertyTypeArray && prop.swiftIvar) { - RLMListBase *list = object_getIvar(obj, prop.swiftIvar); - if (!list._rlmArray) { - list._rlmArray = RLMDynamicGet(obj, prop); - } - return list; - } - return RLMDynamicGet(obj, prop); -} diff --git a/Example/Pods/Realm/Realm/RLMAnalytics.mm b/Example/Pods/Realm/Realm/RLMAnalytics.mm deleted file mode 100644 index b33afd8..0000000 --- a/Example/Pods/Realm/Realm/RLMAnalytics.mm +++ /dev/null @@ -1,243 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -// Asynchronously submits build information to Realm if running in an iOS -// simulator or on OS X if a debugger is attached. Does nothing if running on an -// iOS / watchOS device or if a debugger is *not* attached. -// -// To be clear: this does *not* run when your app is in production or on -// your end-user’s devices; it will only run in the simulator or when a debugger -// is attached. -// -// Why are we doing this? In short, because it helps us build a better product -// for you. None of the data personally identifies you, your employer or your -// app, but it *will* help us understand what language you use, what iOS -// versions you target, etc. Having this info will help prioritizing our time, -// adding new features and deprecating old features. Collecting an anonymized -// bundle & anonymized MAC is the only way for us to count actual usage of the -// other metrics accurately. If we don’t have a way to deduplicate the info -// reported, it will be useless, as a single developer building their Swift app -// 10 times would report 10 times more than a single Objective-C developer that -// only builds once, making the data all but useless. -// No one likes sharing data unless it’s necessary, we get it, and we’ve -// debated adding this for a long long time. Since Realm is a free product -// without an email signup, we feel this is a necessary step so we can collect -// relevant data to build a better product for you. If you truly, absolutely -// feel compelled to not send this data back to Realm, then you can set an env -// variable named REALM_DISABLE_ANALYTICS. Since Realm is free we believe -// letting these analytics run is a small price to pay for the product & support -// we give you. -// -// Currently the following information is reported: -// - What version of Realm is being used, and from which language (obj-c or Swift). -// - What version of OS X it's running on (in case Xcode aggressively drops -// support for older versions again, we need to know what we need to support). -// - The minimum iOS/OS X version that the application is targeting (again, to -// help us decide what versions we need to support). -// - An anonymous MAC address and bundle ID to aggregate the other information on. -// - What version of Swift is being used (if applicable). - -#import "RLMAnalytics.hpp" - -#import - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_MAC || (TARGET_OS_WATCH && TARGET_OS_SIMULATOR) || (TARGET_OS_TV && TARGET_OS_SIMULATOR) -#import "RLMRealm.h" -#import "RLMUtil.hpp" - -#import -#import -#import -#import -#import - -#import - -#ifndef REALM_COCOA_VERSION -#import "RLMVersion.h" -#endif - -#import - -// Declared for RealmSwiftObjectUtil -@interface NSObject (SwiftVersion) -+ (NSString *)swiftVersion; -@end - -// Wrapper for sysctl() that handles the memory management stuff -static auto RLMSysCtl(int *mib, u_int mibSize, size_t *bufferSize) { - std::unique_ptr buffer(nullptr, &free); - - int ret = sysctl(mib, mibSize, nullptr, bufferSize, nullptr, 0); - if (ret != 0) { - return buffer; - } - - buffer.reset(malloc(*bufferSize)); - if (!buffer) { - return buffer; - } - - ret = sysctl(mib, mibSize, buffer.get(), bufferSize, nullptr, 0); - if (ret != 0) { - buffer.reset(); - } - - return buffer; -} - -// Get the version of OS X we're running on (even in the simulator this gives -// the OS X version and not the simulated iOS version) -static NSString *RLMOSVersion() { - std::array mib = {{CTL_KERN, KERN_OSRELEASE}}; - size_t bufferSize; - auto buffer = RLMSysCtl(&mib[0], mib.size(), &bufferSize); - if (!buffer) { - return nil; - } - - return [[NSString alloc] initWithBytesNoCopy:buffer.release() - length:bufferSize - 1 - encoding:NSUTF8StringEncoding - freeWhenDone:YES]; -} - -// Hash the data in the given buffer and convert it to a hex-format string -static NSString *RLMHashData(const void *bytes, size_t length) { - unsigned char buffer[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256(bytes, static_cast(length), buffer); - - char formatted[CC_SHA256_DIGEST_LENGTH * 2 + 1]; - for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i) { - sprintf(formatted + i * 2, "%02x", buffer[i]); - } - - return [[NSString alloc] initWithBytes:formatted - length:CC_SHA256_DIGEST_LENGTH * 2 - encoding:NSUTF8StringEncoding]; -} - -// Returns the hash of the MAC address of the first network adaptor since the -// vendorIdentifier isn't constant between iOS simulators. -static NSString *RLMMACAddress() { - int en0 = static_cast(if_nametoindex("en0")); - if (!en0) { - return nil; - } - - std::array mib = {{CTL_NET, PF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, en0}}; - size_t bufferSize; - auto buffer = RLMSysCtl(&mib[0], mib.size(), &bufferSize); - if (!buffer) { - return nil; - } - - // sockaddr_dl struct is immediately after the if_msghdr struct in the buffer - auto sockaddr = reinterpret_cast(static_cast(buffer.get()) + 1); - auto mac = reinterpret_cast(sockaddr->sdl_data + sockaddr->sdl_nlen); - - return RLMHashData(mac, 6); -} - -static NSDictionary *RLMAnalyticsPayload() { - NSBundle *appBundle = NSBundle.mainBundle; - NSString *hashedBundleID = appBundle.bundleIdentifier; - - // Main bundle isn't always the one of interest (e.g. when running tests - // it's xctest rather than the app's bundle), so look for one with a bundle ID - if (!hashedBundleID) { - for (NSBundle *bundle in NSBundle.allBundles) { - if ((hashedBundleID = bundle.bundleIdentifier)) { - appBundle = bundle; - break; - } - } - } - - // If we found a bundle ID anywhere, hash it as it could contain sensitive - // information (e.g. the name of an unnanounced product) - if (hashedBundleID) { - NSData *data = [hashedBundleID dataUsingEncoding:NSUTF8StringEncoding]; - hashedBundleID = RLMHashData(data.bytes, data.length); - } - - NSString *osVersionString = [[NSProcessInfo processInfo] operatingSystemVersionString]; - Class swiftObjectUtilClass = NSClassFromString(@"RealmSwiftObjectUtil"); - BOOL isSwift = swiftObjectUtilClass != nil; - NSString *swiftVersion = isSwift ? [swiftObjectUtilClass swiftVersion] : @"N/A"; - - static NSString *kUnknownString = @"unknown"; - NSString *hashedMACAddress = RLMMACAddress() ?: kUnknownString; - - return @{ - @"event": @"Run", - @"properties": @{ - // MixPanel properties - @"token": @"ce0fac19508f6c8f20066d345d360fd0", - - // Anonymous identifiers to deduplicate events - @"distinct_id": hashedMACAddress, - @"Anonymized MAC Address": hashedMACAddress, - @"Anonymized Bundle ID": hashedBundleID ?: kUnknownString, - - // Which version of Realm is being used - @"Binding": @"cocoa", - @"Language": isSwift ? @"swift" : @"objc", - @"Realm Version": REALM_COCOA_VERSION, - @"Sync Version": @(REALM_SYNC_VER_STRING), -#if TARGET_OS_WATCH - @"Target OS Type": @"watchos", -#elif TARGET_OS_TV - @"Target OS Type": @"tvos", -#elif TARGET_OS_IPHONE - @"Target OS Type": @"ios", -#else - @"Target OS Type": @"osx", -#endif - @"Swift Version": swiftVersion, - // Current OS version the app is targetting - @"Target OS Version": osVersionString, - // Minimum OS version the app is targetting - @"Target OS Minimum Version": appBundle.infoDictionary[@"MinimumOSVersion"] ?: kUnknownString, - - // Host OS version being built on - @"Host OS Type": @"osx", - @"Host OS Version": RLMOSVersion() ?: kUnknownString, - } - }; -} - -void RLMSendAnalytics() { - if (getenv("REALM_DISABLE_ANALYTICS") || !RLMIsDebuggerAttached() || RLMIsRunningInPlayground()) { - return; - } - - - NSData *payload = [NSJSONSerialization dataWithJSONObject:RLMAnalyticsPayload() options:0 error:nil]; - NSString *url = [NSString stringWithFormat:@"https://api.mixpanel.com/track/?data=%@&ip=1", [payload base64EncodedStringWithOptions:0]]; - - // No error handling or anything because logging errors annoyed people for no - // real benefit, and it's not clear what else we could do - [[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url]] resume]; -} - -#else - -void RLMSendAnalytics() {} - -#endif diff --git a/Example/Pods/Realm/Realm/RLMArray.mm b/Example/Pods/Realm/Realm/RLMArray.mm deleted file mode 100644 index 051267f..0000000 --- a/Example/Pods/Realm/Realm/RLMArray.mm +++ /dev/null @@ -1,439 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMArray_Private.hpp" - -#import "RLMObject_Private.h" -#import "RLMObjectStore.h" -#import "RLMObjectSchema.h" -#import "RLMQueryUtil.hpp" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -#import - -// See -countByEnumeratingWithState:objects:count -@interface RLMArrayHolder : NSObject { -@public - std::unique_ptr items; -} -@end -@implementation RLMArrayHolder -@end - -@implementation RLMArray { -@public - // Backing array when this instance is unmanaged - NSMutableArray *_backingArray; -} - -template -static void changeArray(__unsafe_unretained RLMArray *const ar, - NSKeyValueChange kind, dispatch_block_t f, IndexSetFactory&& is) { - if (!ar->_backingArray) { - ar->_backingArray = [NSMutableArray new]; - } - - if (RLMObjectBase *parent = ar->_parentObject) { - NSIndexSet *indexes = is(); - [parent willChange:kind valuesAtIndexes:indexes forKey:ar->_key]; - f(); - [parent didChange:kind valuesAtIndexes:indexes forKey:ar->_key]; - } - else { - f(); - } -} - -static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSUInteger index, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndex:index]; }); -} - -static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSRange range, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndexesInRange:range]; }); -} - -static void changeArray(__unsafe_unretained RLMArray *const ar, NSKeyValueChange kind, NSIndexSet *is, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return is; }); -} - -- (instancetype)initWithObjectClassName:(__unsafe_unretained NSString *const)objectClassName { - self = [super init]; - if (self) { - _objectClassName = objectClassName; - } - return self; -} - -- (RLMRealm *)realm { - return nil; -} - -// -// Generic implementations for all RLMArray variants -// - -- (id)firstObject { - if (self.count) { - return [self objectAtIndex:0]; - } - return nil; -} - -- (id)lastObject { - NSUInteger count = self.count; - if (count) { - return [self objectAtIndex:count-1]; - } - return nil; -} - -- (void)addObjects:(id)objects { - for (id obj in objects) { - [self addObject:obj]; - } -} - -- (void)addObject:(RLMObject *)object { - [self insertObject:object atIndex:self.count]; -} - -- (void)removeLastObject { - NSUInteger count = self.count; - if (count) { - [self removeObjectAtIndex:count-1]; - } -} - -- (id)objectAtIndexedSubscript:(NSUInteger)index { - return [self objectAtIndex:index]; -} - -- (void)setObject:(id)newValue atIndexedSubscript:(NSUInteger)index { - [self replaceObjectAtIndex:index withObject:newValue]; -} - -// -// Unmanaged RLMArray implementation -// - -static void RLMValidateMatchingObjectType(RLMArray *array, RLMObject *object) { - if (!object) { - @throw RLMException(@"Object must not be nil"); - } - if (!object->_objectSchema) { - @throw RLMException(@"Object cannot be inserted unless the schema is initialized. " - "This can happen if you try to insert objects into a RLMArray / List from a default value or from an overriden unmanaged initializer (`init()`)."); - } - if (![array->_objectClassName isEqualToString:object->_objectSchema.className]) { - @throw RLMException(@"Object type '%@' does not match RLMArray type '%@'.", - object->_objectSchema.className, array->_objectClassName); - } -} - -static void RLMValidateArrayBounds(__unsafe_unretained RLMArray *const ar, - NSUInteger index, bool allowOnePastEnd=false) { - NSUInteger max = ar->_backingArray.count + allowOnePastEnd; - if (index >= max) { - @throw RLMException(@"Index %llu is out of bounds (must be less than %llu).", - (unsigned long long)index, (unsigned long long)max); - } -} - -- (id)objectAtIndex:(NSUInteger)index { - RLMValidateArrayBounds(self, index); - if (!_backingArray) { - _backingArray = [NSMutableArray new]; - } - return [_backingArray objectAtIndex:index]; -} - -- (NSUInteger)count { - return _backingArray.count; -} - -- (BOOL)isInvalidated { - return NO; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unused __unsafe_unretained id [])buffer count:(__unused NSUInteger)len { - if (state->state != 0) { - return 0; - } - - // We need to enumerate a copy of the backing array so that it doesn't - // reflect changes made during enumeration. This copy has to be autoreleased - // (since there's nowhere for us to store a strong reference), and uses - // RLMArrayHolder rather than an NSArray because NSArray doesn't guarantee - // that it'll use a single contiguous block of memory, and if it doesn't - // we'd need to forward multiple calls to this method to the same NSArray, - // which would require holding a reference to it somewhere. - __autoreleasing RLMArrayHolder *copy = [[RLMArrayHolder alloc] init]; - copy->items = std::make_unique(self.count); - - NSUInteger i = 0; - for (id object in _backingArray) { - copy->items[i++] = object; - } - - state->itemsPtr = (__unsafe_unretained id *)(void *)copy->items.get(); - // needs to point to something valid, but the whole point of this is so - // that it can't be changed - state->mutationsPtr = state->extra; - state->state = i; - - return i; -} - -- (void)addObjectsFromArray:(NSArray *)array { - for (id obj in array) { - RLMValidateMatchingObjectType(self, obj); - } - changeArray(self, NSKeyValueChangeInsertion, NSMakeRange(_backingArray.count, array.count), ^{ - [_backingArray addObjectsFromArray:array]; - }); -} - -- (void)insertObject:(RLMObject *)anObject atIndex:(NSUInteger)index { - RLMValidateMatchingObjectType(self, anObject); - RLMValidateArrayBounds(self, index, true); - changeArray(self, NSKeyValueChangeInsertion, index, ^{ - [_backingArray insertObject:anObject atIndex:index]; - }); -} - -- (void)insertObjects:(id)objects atIndexes:(NSIndexSet *)indexes { - changeArray(self, NSKeyValueChangeInsertion, indexes, ^{ - NSUInteger currentIndex = [indexes firstIndex]; - for (RLMObject *obj in objects) { - RLMValidateMatchingObjectType(self, obj); - [_backingArray insertObject:obj atIndex:currentIndex]; - currentIndex = [indexes indexGreaterThanIndex:currentIndex]; - } - }); -} - -- (void)removeObjectAtIndex:(NSUInteger)index { - RLMValidateArrayBounds(self, index); - changeArray(self, NSKeyValueChangeRemoval, index, ^{ - [_backingArray removeObjectAtIndex:index]; - }); -} - -- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes { - changeArray(self, NSKeyValueChangeRemoval, indexes, ^{ - [_backingArray removeObjectsAtIndexes:indexes]; - }); -} - -- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { - RLMValidateMatchingObjectType(self, anObject); - RLMValidateArrayBounds(self, index); - changeArray(self, NSKeyValueChangeReplacement, index, ^{ - [_backingArray replaceObjectAtIndex:index withObject:anObject]; - }); -} - -- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex { - RLMValidateArrayBounds(self, sourceIndex); - RLMValidateArrayBounds(self, destinationIndex); - RLMObjectBase *original = _backingArray[sourceIndex]; - - auto start = std::min(sourceIndex, destinationIndex); - auto len = std::max(sourceIndex, destinationIndex) - start + 1; - changeArray(self, NSKeyValueChangeReplacement, {start, len}, ^{ - [_backingArray removeObjectAtIndex:sourceIndex]; - [_backingArray insertObject:original atIndex:destinationIndex]; - }); -} - -- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 { - RLMValidateArrayBounds(self, index1); - RLMValidateArrayBounds(self, index2); - - changeArray(self, NSKeyValueChangeReplacement, ^{ - [_backingArray exchangeObjectAtIndex:index1 withObjectAtIndex:index2]; - }, [=] { - NSMutableIndexSet *set = [[NSMutableIndexSet alloc] initWithIndex:index1]; - [set addIndex:index2]; - return set; - }); -} - -- (NSUInteger)indexOfObject:(RLMObject *)object { - RLMValidateMatchingObjectType(self, object); - NSUInteger index = 0; - for (RLMObject *cmp in _backingArray) { - if (RLMObjectBaseAreEqual(object, cmp)) { - return index; - } - index++; - } - return NSNotFound; -} - -- (void)removeAllObjects { - changeArray(self, NSKeyValueChangeRemoval, NSMakeRange(0, _backingArray.count), ^{ - [_backingArray removeAllObjects]; - }); -} - -- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ... -{ - va_list args; - va_start(args, predicateFormat); - RLMResults *results = [self objectsWhere:predicateFormat args:args]; - va_end(args); - return results; -} - -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args -{ - return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]]; -} - -- (id)valueForKeyPath:(NSString *)keyPath { - if (!_backingArray) { - return [super valueForKeyPath:keyPath]; - } - // Although delegating to valueForKeyPath: here would allow to support - // nested key paths as well, limiting functionality gives consistency - // between unmanaged and managed arrays. - if ([keyPath characterAtIndex:0] == '@') { - NSRange operatorRange = [keyPath rangeOfString:@"." options:NSLiteralSearch]; - if (operatorRange.location != NSNotFound) { - NSString *operatorKeyPath = [keyPath substringFromIndex:operatorRange.location + 1]; - if ([operatorKeyPath rangeOfString:@"."].location != NSNotFound) { - @throw RLMException(@"Nested key paths are not supported yet for KVC collection operators."); - } - } - } - return [_backingArray valueForKeyPath:keyPath]; -} - -- (id)valueForKey:(NSString *)key { - if ([key isEqualToString:RLMInvalidatedKey]) { - return @NO; // Unmanaged arrays are never invalidated - } - if (!_backingArray) { - return @[]; - } - return [_backingArray valueForKey:key]; -} - -- (void)setValue:(id)value forKey:(NSString *)key { - [_backingArray setValue:value forKey:key]; -} - -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate { - if (!_backingArray) { - return NSNotFound; - } - return [_backingArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger, BOOL *) { - return [predicate evaluateWithObject:obj]; - }]; -} - -- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes { - if (!_backingArray) { - _backingArray = [NSMutableArray new]; - } - return [_backingArray objectsAtIndexes:indexes]; -} - -- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { - RLMValidateArrayObservationKey(keyPath, self); - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -// -// Methods unsupported on unmanaged RLMArray instances -// - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" - -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate -{ - @throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm"); -} - -- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending -{ - return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]]; -} - -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties -{ - @throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm"); -} - -// The compiler complains about the method's argument type not matching due to -// it not having the generic type attached, but it doesn't seem to be possible -// to actually include the generic type -// http://www.openradar.me/radar?id=6135653276319744 -#pragma clang diagnostic ignored "-Wmismatched-parameter-types" -- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray *, RLMCollectionChange *, NSError *))block { - @throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm"); -} -#pragma clang diagnostic pop - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ... -{ - va_list args; - va_start(args, predicateFormat); - NSUInteger index = [self indexOfObjectWhere:predicateFormat args:args]; - va_end(args); - return index; -} - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args -{ - return [self indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:predicateFormat - arguments:args]]; -} - -#pragma mark - Superclass Overrides - -- (NSString *)description { - return [self descriptionWithMaxDepth:RLMDescriptionMaxDepth]; -} - -- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth { - return RLMDescriptionWithMaxDepth(@"RLMArray", self, depth); -} -@end - -@interface RLMSortDescriptor () -@property (nonatomic, strong) NSString *property; -@property (nonatomic, assign) BOOL ascending; -@end - -@implementation RLMSortDescriptor -+ (instancetype)sortDescriptorWithProperty:(NSString *)propertyName ascending:(BOOL)ascending { - RLMSortDescriptor *desc = [[RLMSortDescriptor alloc] init]; - desc->_property = propertyName; - desc->_ascending = ascending; - return desc; -} - -- (instancetype)reversedSortDescriptor { - return [self.class sortDescriptorWithProperty:_property ascending:!_ascending]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMArrayLinkView.mm b/Example/Pods/Realm/Realm/RLMArrayLinkView.mm deleted file mode 100644 index c045627..0000000 --- a/Example/Pods/Realm/Realm/RLMArrayLinkView.mm +++ /dev/null @@ -1,429 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMArray_Private.hpp" - -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObject_Private.hpp" -#import "RLMObservation.hpp" -#import "RLMProperty_Private.h" -#import "RLMQueryUtil.hpp" -#import "RLMRealm_Private.hpp" -#import "RLMSchema.h" -#import "RLMUtil.hpp" - -#import "list.hpp" -#import "results.hpp" - -#import -#import - -// -// RLMArray implementation -// -@implementation RLMArrayLinkView { -@public - realm::List _backingList; - RLMRealm *_realm; - RLMClassInfo *_objectInfo; - RLMClassInfo *_ownerInfo; - std::unique_ptr _observationInfo; -} - -- (RLMArrayLinkView *)initWithParent:(__unsafe_unretained RLMObjectBase *const)parentObject - property:(__unsafe_unretained RLMProperty *const)property { - self = [self initWithObjectClassName:property.objectClassName]; - if (self) { - _realm = parentObject->_realm; - _backingList = realm::List(_realm->_realm, parentObject->_row.get_linklist(parentObject->_info->tableColumn(property))); - _objectInfo = &parentObject->_info->linkTargetType(property.index); - _ownerInfo = parentObject->_info; - _key = property.name; - } - return self; -} - -void RLMValidateArrayObservationKey(__unsafe_unretained NSString *const keyPath, - __unsafe_unretained RLMArray *const array) { - if (![keyPath isEqualToString:RLMInvalidatedKey]) { - @throw RLMException(@"[<%@ %p> addObserver:forKeyPath:options:context:] is not supported. Key path: %@", - [array class], array, keyPath); - } -} - -void RLMEnsureArrayObservationInfo(std::unique_ptr& info, - __unsafe_unretained NSString *const keyPath, - __unsafe_unretained RLMArray *const array, - __unsafe_unretained id const observed) { - RLMValidateArrayObservationKey(keyPath, array); - if (!info && array.class == [RLMArrayLinkView class]) { - RLMArrayLinkView *lv = static_cast(array); - info = std::make_unique(*lv->_ownerInfo, - lv->_backingList.get_origin_row_index(), - observed); - } -} - -// -// validation helpers -// -[[gnu::noinline]] -[[noreturn]] -static void throwError() { - try { - throw; - } - catch (realm::InvalidTransactionException const&) { - @throw RLMException(@"Cannot modify managed RLMArray outside of a write transaction"); - } - catch (realm::IncorrectThreadException const&) { - @throw RLMException(@"Realm accessed from incorrect thread"); - } - catch (realm::List::InvalidatedException const&) { - @throw RLMException(@"RLMArray has been invalidated or the containing object has been deleted"); - } - catch (realm::List::OutOfBoundsIndexException const& e) { - @throw RLMException(@"Index %zu is out of bounds (must be less than %zu)", - e.requested, e.valid_count); - } -} - -template -static auto translateErrors(Function&& f) { - try { - return f(); - } - catch (...) { - throwError(); - } -} - -static void validateObjectToAdd(__unsafe_unretained RLMArrayLinkView *const ar, - __unsafe_unretained RLMObject *const obj) { - if (!obj) { - @throw RLMException(@"Cannot add `nil` to RLMArray<%@>", ar->_objectClassName); - } - - NSString *objectClassName = obj->_objectSchema.className; - if (![objectClassName isEqualToString:ar->_objectClassName]) { - @throw RLMException(@"Cannot add object of type '%@' to RLMArray<%@>", - objectClassName, ar->_objectClassName); - } - - if (obj->_realm != ar.realm) { - [ar.realm addObject:obj]; - } - else if (obj->_realm && !obj->_row.is_attached()) { - @throw RLMException(@"Object has been deleted or invalidated."); - } -} - -template -static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, - NSKeyValueChange kind, dispatch_block_t f, IndexSetFactory&& is) { - translateErrors([&] { ar->_backingList.verify_in_transaction(); }); - RLMObservationInfo *info = RLMGetObservationInfo(ar->_observationInfo.get(), - ar->_backingList.get_origin_row_index(), - *ar->_ownerInfo); - if (info) { - NSIndexSet *indexes = is(); - info->willChange(ar->_key, kind, indexes); - try { - f(); - } - catch (...) { - info->didChange(ar->_key, kind, indexes); - throwError(); - } - info->didChange(ar->_key, kind, indexes); - } - else { - translateErrors([&] { f(); }); - } -} - -static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSUInteger index, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndex:index]; }); -} - -static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSRange range, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return [NSIndexSet indexSetWithIndexesInRange:range]; }); -} - -static void changeArray(__unsafe_unretained RLMArrayLinkView *const ar, NSKeyValueChange kind, NSIndexSet *is, dispatch_block_t f) { - changeArray(ar, kind, f, [=] { return is; }); -} - -// -// public method implementations -// -- (RLMRealm *)realm { - return _realm; -} - -- (NSUInteger)count { - return translateErrors([&] { return _backingList.size(); }); -} - -- (BOOL)isInvalidated { - return translateErrors([&] { return !_backingList.is_valid(); }); -} - -- (RLMClassInfo *)objectInfo { - return _objectInfo; -} - -- (BOOL)isEqual:(id)object { - if (RLMArrayLinkView *linkView = RLMDynamicCast(object)) { - return linkView->_backingList == _backingList; - } - return NO; -} - -- (NSUInteger)hash { - return std::hash()(_backingList); -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(__unused __unsafe_unretained id [])buffer - count:(NSUInteger)len { - __autoreleasing RLMFastEnumerator *enumerator; - if (state->state == 0) { - translateErrors([&] { _backingList.verify_attached(); }); - - enumerator = [[RLMFastEnumerator alloc] initWithCollection:self objectSchema:*_objectInfo]; - state->extra[0] = (long)enumerator; - state->extra[1] = self.count; - } - else { - enumerator = (__bridge id)(void *)state->extra[0]; - } - - return [enumerator countByEnumeratingWithState:state count:len]; -} - -- (id)objectAtIndex:(NSUInteger)index { - return RLMCreateObjectAccessor(_realm, *_objectInfo, - translateErrors([&] { return _backingList.get(index).get_index(); })); -} - -static void RLMInsertObject(RLMArrayLinkView *ar, RLMObject *object, NSUInteger index) { - if (index == NSUIntegerMax) { - index = translateErrors([&] { return ar->_backingList.size(); }); - } - - validateObjectToAdd(ar, object); - changeArray(ar, NSKeyValueChangeInsertion, index, ^{ - ar->_backingList.insert(index, object->_row.get_index()); - }); -} - -- (void)addObject:(RLMObject *)object { - RLMInsertObject(self, object, NSUIntegerMax); -} - -- (void)insertObject:(RLMObject *)object atIndex:(NSUInteger)index { - RLMInsertObject(self, object, index); -} - -- (void)insertObjects:(id)objects atIndexes:(NSIndexSet *)indexes { - changeArray(self, NSKeyValueChangeInsertion, indexes, ^{ - NSUInteger index = [indexes firstIndex]; - for (RLMObject *obj in objects) { - validateObjectToAdd(self, obj); - _backingList.insert(index, obj->_row.get_index()); - index = [indexes indexGreaterThanIndex:index]; - } - }); -} - - -- (void)removeObjectAtIndex:(NSUInteger)index { - changeArray(self, NSKeyValueChangeRemoval, index, ^{ - _backingList.remove(index); - }); -} - -- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes { - changeArray(self, NSKeyValueChangeRemoval, indexes, ^{ - [indexes enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger idx, BOOL *) { - _backingList.remove(idx); - }]; - }); -} - -- (void)addObjectsFromArray:(NSArray *)array { - changeArray(self, NSKeyValueChangeInsertion, NSMakeRange(self.count, array.count), ^{ - for (RLMObject *obj in array) { - validateObjectToAdd(self, obj); - _backingList.add(obj->_row.get_index()); - } - }); -} - -- (void)removeAllObjects { - changeArray(self, NSKeyValueChangeRemoval, NSMakeRange(0, self.count), ^{ - _backingList.remove_all(); - }); -} - -- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(RLMObject *)object { - validateObjectToAdd(self, object); - changeArray(self, NSKeyValueChangeReplacement, index, ^{ - _backingList.set(index, object->_row.get_index()); - }); -} - -- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex { - auto start = std::min(sourceIndex, destinationIndex); - auto len = std::max(sourceIndex, destinationIndex) - start + 1; - changeArray(self, NSKeyValueChangeReplacement, {start, len}, ^{ - _backingList.move(sourceIndex, destinationIndex); - }); -} - -- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2 { - changeArray(self, NSKeyValueChangeReplacement, ^{ - _backingList.swap(index1, index2); - }, [=] { - NSMutableIndexSet *set = [[NSMutableIndexSet alloc] initWithIndex:index1]; - [set addIndex:index2]; - return set; - }); -} - -- (NSUInteger)indexOfObject:(RLMObject *)object { - if (object.invalidated) { - @throw RLMException(@"Object has been deleted or invalidated"); - } - - // check that object types align - if (![_objectClassName isEqualToString:object->_objectSchema.className]) { - @throw RLMException(@"Object of type (%@) does not match RLMArray type (%@)", - object->_objectSchema.className, _objectClassName); - } - - return translateErrors([&] { return RLMConvertNotFound(_backingList.find(object->_row)); }); -} - -- (id)valueForKeyPath:(NSString *)keyPath { - if ([keyPath hasPrefix:@"@"]) { - // Delegate KVC collection operators to RLMResults - auto query = translateErrors([&] { return _backingList.get_query(); }); - RLMResults *results = [RLMResults resultsWithObjectInfo:*_objectInfo - results:realm::Results(_realm->_realm, std::move(query))]; - return [results valueForKeyPath:keyPath]; - } - return [super valueForKeyPath:keyPath]; -} - -- (id)valueForKey:(NSString *)key { - // Ideally we'd use "@invalidated" for this so that "invalidated" would use - // normal array KVC semantics, but observing @things works very oddly (when - // it's part of a key path, it's triggered automatically when array index - // changes occur, and can't be sent explicitly, but works normally when it's - // the entire key path), and an RLMArrayLinkView *can't* have objects where - // invalidated is true, so we're not losing much. - if ([key isEqualToString:RLMInvalidatedKey]) { - return @(!_backingList.is_valid()); - } - - translateErrors([&] { _backingList.verify_attached(); }); - return RLMCollectionValueForKey(self, key); -} - -- (void)setValue:(id)value forKey:(NSString *)key { - translateErrors([&] { _backingList.verify_in_transaction(); }); - RLMCollectionSetValueForKey(self, key, value); -} - -- (void)deleteObjectsFromRealm { - // delete all target rows from the realm - RLMTrackDeletions(_realm, ^{ - translateErrors([&] { _backingList.delete_all(); }); - }); -} - -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { - if (properties.count == 0) { - auto results = translateErrors([&] { return _backingList.filter({}); }); - return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)]; - } - - auto order = RLMSortDescriptorFromDescriptors(*_objectInfo->table(), properties); - auto results = translateErrors([&] { return _backingList.sort(std::move(order)); }); - return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)]; -} - -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate { - auto query = RLMPredicateToQuery(predicate, _objectInfo->rlmObjectSchema, _realm.schema, _realm.group); - auto results = translateErrors([&] { return _backingList.filter(std::move(query)); }); - return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)]; -} - -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate { - auto query = translateErrors([&] { return _backingList.get_query(); }); - query.and_query(RLMPredicateToQuery(predicate, _objectInfo->rlmObjectSchema, _realm.schema, _realm.group)); -#if REALM_VER_MAJOR >= 2 - auto indexInTable = query.find(); - if (indexInTable == realm::not_found) { - return NSNotFound; - } - auto row = query.get_table()->get(indexInTable); - return _backingList.find(row); -#else - return RLMConvertNotFound(query.find()); -#endif -} - -- (NSArray *)objectsAtIndexes:(__unused NSIndexSet *)indexes { - // FIXME: this is called by KVO when array changes are made. It's not clear - // why, and returning nil seems to work fine. - return nil; -} - -- (void)addObserver:(id)observer - forKeyPath:(NSString *)keyPath - options:(NSKeyValueObservingOptions)options - context:(void *)context { - RLMEnsureArrayObservationInfo(_observationInfo, keyPath, self, self); - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -- (NSUInteger)indexInSource:(NSUInteger)index { - return _backingList.get_unchecked(index); -} - -- (realm::TableView)tableView { - return translateErrors([&] { return _backingList.get_query(); }).find_all(); -} - -// The compiler complains about the method's argument type not matching due to -// it not having the generic type attached, but it doesn't seem to be possible -// to actually include the generic type -// http://www.openradar.me/radar?id=6135653276319744 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wmismatched-parameter-types" -- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray *, RLMCollectionChange *, NSError *))block { - [_realm verifyNotificationsAreSupported]; - return RLMAddNotificationBlock(self, _backingList, block); -} -#pragma clang diagnostic pop - -@end diff --git a/Example/Pods/Realm/Realm/RLMAuthResponseModel.m b/Example/Pods/Realm/Realm/RLMAuthResponseModel.m deleted file mode 100644 index 2eb5b7c..0000000 --- a/Example/Pods/Realm/Realm/RLMAuthResponseModel.m +++ /dev/null @@ -1,57 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMAuthResponseModel.h" - -#import "RLMTokenModels.h" -#import "RLMSyncUtil_Private.h" - -static const NSString *const kRLMSyncAccessTokenKey = @"access_token"; -static const NSString *const kRLMSyncRefreshTokenKey = @"refresh_token"; - -@interface RLMAuthResponseModel () - -@property (nonatomic, readwrite) RLMTokenModel *accessToken; -@property (nonatomic, readwrite) RLMTokenModel *refreshToken; - -@end - -@implementation RLMAuthResponseModel - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary - requireAccessToken:(BOOL)requireAccessToken - requireRefreshToken:(BOOL)requireRefreshToken { - if (self = [super init]) { - // Get the access token. - if (requireAccessToken) { - RLM_SYNC_PARSE_MODEL_OR_ABORT(jsonDictionary, kRLMSyncAccessTokenKey, RLMTokenModel, accessToken); - } else { - RLM_SYNC_PARSE_OPTIONAL_MODEL(jsonDictionary, kRLMSyncAccessTokenKey, RLMTokenModel, accessToken); - } - // Get the refresh token. - if (requireRefreshToken) { - RLM_SYNC_PARSE_MODEL_OR_ABORT(jsonDictionary, kRLMSyncRefreshTokenKey, RLMTokenModel, refreshToken); - } else { - RLM_SYNC_PARSE_OPTIONAL_MODEL(jsonDictionary, kRLMSyncRefreshTokenKey, RLMTokenModel, refreshToken); - } - return self; - } - return nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMClassInfo.mm b/Example/Pods/Realm/Realm/RLMClassInfo.mm deleted file mode 100644 index b0ff82b..0000000 --- a/Example/Pods/Realm/Realm/RLMClassInfo.mm +++ /dev/null @@ -1,107 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMClassInfo.hpp" - -#import "RLMRealm_Private.hpp" -#import "RLMObjectSchema_Private.h" -#import "RLMSchema.h" -#import "RLMProperty_Private.h" -#import "RLMQueryUtil.hpp" -#import "RLMUtil.hpp" - -#import "object_schema.hpp" -#import "object_store.hpp" -#import "schema.hpp" - -#import - -using namespace realm; - -RLMClassInfo::RLMClassInfo(RLMRealm *realm, RLMObjectSchema *rlmObjectSchema, - const realm::ObjectSchema *objectSchema) -: realm(realm), rlmObjectSchema(rlmObjectSchema), objectSchema(objectSchema) { } - -realm::Table *RLMClassInfo::table() const { - if (!m_table) { - m_table = ObjectStore::table_for_object_type(realm.group, objectSchema->name).get(); - } - return m_table; -} - -RLMProperty *RLMClassInfo::propertyForTableColumn(NSUInteger col) const noexcept { - auto const& props = objectSchema->persisted_properties; - for (size_t i = 0; i < props.size(); ++i) { - if (props[i].table_column == col) { - return rlmObjectSchema.properties[i]; - } - } - return nil; -} - -RLMProperty *RLMClassInfo::propertyForPrimaryKey() const noexcept { - return rlmObjectSchema.primaryKeyProperty; -} - -NSUInteger RLMClassInfo::tableColumn(NSString *propertyName) const { - return tableColumn(RLMValidatedProperty(rlmObjectSchema, propertyName)); -} - -NSUInteger RLMClassInfo::tableColumn(RLMProperty *property) const { - return objectSchema->persisted_properties[property.index].table_column; -} - -RLMClassInfo &RLMClassInfo::linkTargetType(size_t index) { - if (index < m_linkTargets.size() && m_linkTargets[index]) { - return *m_linkTargets[index]; - } - if (m_linkTargets.size() <= index) { - m_linkTargets.resize(index + 1); - } - m_linkTargets[index] = &realm->_info[rlmObjectSchema.properties[index].objectClassName]; - return *m_linkTargets[index]; -} - -RLMSchemaInfo::impl::iterator RLMSchemaInfo::begin() noexcept { return m_objects.begin(); } -RLMSchemaInfo::impl::iterator RLMSchemaInfo::end() noexcept { return m_objects.end(); } -RLMSchemaInfo::impl::const_iterator RLMSchemaInfo::begin() const noexcept { return m_objects.begin(); } -RLMSchemaInfo::impl::const_iterator RLMSchemaInfo::end() const noexcept { return m_objects.end(); } - -RLMClassInfo& RLMSchemaInfo::operator[](NSString *name) { - auto it = m_objects.find(name); - if (it == m_objects.end()) { - @throw RLMException(@"Object type '%@' is not managed by the Realm. " - @"If using a custom `objectClasses` / `objectTypes` array in your configuration, " - @"add `%@` to the list of `objectClasses` / `objectTypes`.", - name, name); - } - return *&it->second; -} - -RLMSchemaInfo::RLMSchemaInfo(RLMRealm *realm, RLMSchema *rlmSchema, realm::Schema const& schema) { - REALM_ASSERT(rlmSchema.objectSchema.count == schema.size()); - REALM_ASSERT(m_objects.empty()); - - m_objects.reserve(schema.size()); - for (RLMObjectSchema *rlmObjectSchema in rlmSchema.objectSchema) { - m_objects.emplace(std::piecewise_construct, - std::forward_as_tuple(rlmObjectSchema.className), - std::forward_as_tuple(realm, rlmObjectSchema, - &*schema.find(rlmObjectSchema.objectName.UTF8String))); - } -} diff --git a/Example/Pods/Realm/Realm/RLMCollection.mm b/Example/Pods/Realm/Realm/RLMCollection.mm deleted file mode 100644 index b039d99..0000000 --- a/Example/Pods/Realm/Realm/RLMCollection.mm +++ /dev/null @@ -1,355 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMCollection_Private.hpp" - -#import "RLMArray_Private.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObject_Private.hpp" - -#import "collection_notifications.hpp" -#import "list.hpp" -#import "results.hpp" - -#import - -static const int RLMEnumerationBufferSize = 16; - -@implementation RLMFastEnumerator { - // The buffer supplied by fast enumeration does not retain the objects given - // to it, but because we create objects on-demand and don't want them - // autoreleased (a table can have more rows than the device has memory for - // accessor objects) we need a thing to retain them. - id _strongBuffer[RLMEnumerationBufferSize]; - - RLMRealm *_realm; - RLMClassInfo *_info; - - // Collection being enumerated. Only one of these two will be valid: when - // possible we enumerate the collection directly, but when in a write - // transaction we instead create a frozen TableView and enumerate that - // instead so that mutating the collection during enumeration works. - id _collection; - realm::TableView _tableView; -} - -- (instancetype)initWithCollection:(id)collection objectSchema:(RLMClassInfo&)info { - self = [super init]; - if (self) { - _realm = collection.realm; - _info = &info; - - if (_realm.inWriteTransaction) { - _tableView = [collection tableView]; - } - else { - _collection = collection; - [_realm registerEnumerator:self]; - } - } - return self; -} - -- (void)dealloc { - if (_collection) { - [_realm unregisterEnumerator:self]; - } -} - -- (void)detach { - _tableView = [_collection tableView]; - _collection = nil; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - count:(NSUInteger)len { - [_realm verifyThread]; - if (!_tableView.is_attached() && !_collection) { - @throw RLMException(@"Collection is no longer valid"); - } - // The fast enumeration buffer size is currently a hardcoded number in the - // compiler so this can't actually happen, but just in case it changes in - // the future... - if (len > RLMEnumerationBufferSize) { - len = RLMEnumerationBufferSize; - } - - NSUInteger batchCount = 0, count = state->extra[1]; - - Class accessorClass = _info->rlmObjectSchema.accessorClass; - for (NSUInteger index = state->state; index < count && batchCount < len; ++index) { - RLMObject *accessor = RLMCreateManagedAccessor(accessorClass, _realm, _info); - if (_collection) { - accessor->_row = (*_info->table())[[_collection indexInSource:index]]; - } - else if (_tableView.is_row_attached(index)) { - accessor->_row = (*_info->table())[_tableView.get_source_ndx(index)]; - } - RLMInitializeSwiftAccessorGenerics(accessor); - _strongBuffer[batchCount] = accessor; - batchCount++; - } - - for (NSUInteger i = batchCount; i < len; ++i) { - _strongBuffer[i] = nil; - } - - if (batchCount == 0) { - // Release our data if we're done, as we're autoreleased and so may - // stick around for a while - _collection = nil; - if (_tableView.is_attached()) { - _tableView = {}; - } - else { - [_realm unregisterEnumerator:self]; - } - } - - state->itemsPtr = (__unsafe_unretained id *)(void *)_strongBuffer; - state->state += batchCount; - state->mutationsPtr = state->extra+1; - - return batchCount; -} -@end - - -NSArray *RLMCollectionValueForKey(id collection, NSString *key) { - size_t count = collection.count; - if (count == 0) { - return @[]; - } - - RLMRealm *realm = collection.realm; - RLMClassInfo *info = collection.objectInfo; - - NSMutableArray *results = [NSMutableArray arrayWithCapacity:count]; - if ([key isEqualToString:@"self"]) { - for (size_t i = 0; i < count; i++) { - size_t rowIndex = [collection indexInSource:i]; - [results addObject:RLMCreateObjectAccessor(realm, *info, rowIndex) ?: NSNull.null]; - } - return results; - } - - RLMObject *accessor = RLMCreateManagedAccessor(info->rlmObjectSchema.accessorClass, realm, info); - realm::Table *table = info->table(); - for (size_t i = 0; i < count; i++) { - size_t rowIndex = [collection indexInSource:i]; - accessor->_row = (*table)[rowIndex]; - RLMInitializeSwiftAccessorGenerics(accessor); - [results addObject:[accessor valueForKey:key] ?: NSNull.null]; - } - - return results; -} - -void RLMCollectionSetValueForKey(id collection, NSString *key, id value) { - realm::TableView tv = [collection tableView]; - if (tv.size() == 0) { - return; - } - - RLMRealm *realm = collection.realm; - RLMClassInfo *info = collection.objectInfo; - RLMObject *accessor = RLMCreateManagedAccessor(info->rlmObjectSchema.accessorClass, realm, info); - for (size_t i = 0; i < tv.size(); i++) { - accessor->_row = tv[i]; - RLMInitializeSwiftAccessorGenerics(accessor); - [accessor setValue:value forKey:key]; - } -} - -NSString *RLMDescriptionWithMaxDepth(NSString *name, - id collection, - NSUInteger depth) { - if (depth == 0) { - return @""; - } - - const NSUInteger maxObjects = 100; - auto str = [NSMutableString stringWithFormat:@"%@ <%p> (\n", name, (void *)collection]; - size_t index = 0, skipped = 0; - for (id obj in collection) { - NSString *sub; - if ([obj respondsToSelector:@selector(descriptionWithMaxDepth:)]) { - sub = [obj descriptionWithMaxDepth:depth - 1]; - } - else { - sub = [obj description]; - } - - // Indent child objects - NSString *objDescription = [sub stringByReplacingOccurrencesOfString:@"\n" - withString:@"\n\t"]; - [str appendFormat:@"\t[%zu] %@,\n", index++, objDescription]; - if (index >= maxObjects) { - skipped = collection.count - maxObjects; - break; - } - } - - // Remove last comma and newline characters - if (collection.count > 0) { - [str deleteCharactersInRange:NSMakeRange(str.length-2, 2)]; - } - if (skipped) { - [str appendFormat:@"\n\t... %zu objects skipped.", skipped]; - } - [str appendFormat:@"\n)"]; - return str; -} - -@implementation RLMCancellationToken { - realm::NotificationToken _token; - __unsafe_unretained RLMRealm *_realm; -} -- (instancetype)initWithToken:(realm::NotificationToken)token realm:(RLMRealm *)realm { - self = [super init]; - if (self) { - _token = std::move(token); - _realm = realm; - } - return self; -} - -- (RLMRealm *)realm { - return _realm; -} - -- (void)suppressNextNotification { - _token.suppress_next(); -} - -- (void)stop { - _token = {}; -} - -@end - -@implementation RLMCollectionChange { - realm::CollectionChangeSet _indices; -} - -- (instancetype)initWithChanges:(realm::CollectionChangeSet)indices { - self = [super init]; - if (self) { - _indices = std::move(indices); - } - return self; -} - -static NSArray *toArray(realm::IndexSet const& set) { - NSMutableArray *ret = [NSMutableArray new]; - for (auto index : set.as_indexes()) { - [ret addObject:@(index)]; - } - return ret; -} - -- (NSArray *)insertions { - return toArray(_indices.insertions); -} - -- (NSArray *)deletions { - return toArray(_indices.deletions); -} - -- (NSArray *)modifications { - return toArray(_indices.modifications); -} - -static NSArray *toIndexPathArray(realm::IndexSet const& set, NSUInteger section) { - NSMutableArray *ret = [NSMutableArray new]; - NSUInteger path[2] = {section, 0}; - for (auto index : set.as_indexes()) { - path[1] = index; - [ret addObject:[NSIndexPath indexPathWithIndexes:path length:2]]; - } - return ret; -} - -- (NSArray *)deletionsInSection:(NSUInteger)section { - return toIndexPathArray(_indices.deletions, section); -} - -- (NSArray *)insertionsInSection:(NSUInteger)section { - return toIndexPathArray(_indices.insertions, section); - -} - -- (NSArray *)modificationsInSection:(NSUInteger)section { - return toIndexPathArray(_indices.modifications, section); - -} -@end - -template -RLMNotificationToken *RLMAddNotificationBlock(id objcCollection, - Collection& collection, - void (^block)(id, RLMCollectionChange *, NSError *), - bool suppressInitialChange) { - struct IsValid { - static bool call(realm::List const& list) { - return list.is_valid(); - } - static bool call(realm::Results const&) { - return true; - } - }; - - auto skip = suppressInitialChange ? std::make_shared(true) : nullptr; - auto cb = [=, &collection](realm::CollectionChangeSet const& changes, - std::exception_ptr err) { - if (err) { - try { - rethrow_exception(err); - } - catch (...) { - NSError *error = nil; - RLMRealmTranslateException(&error); - block(nil, nil, error); - return; - } - } - - if (!IsValid::call(collection)) { - return; - } - - if (skip && *skip) { - *skip = false; - block(objcCollection, nil, nil); - } - else if (changes.empty()) { - block(objcCollection, nil, nil); - } - else { - block(objcCollection, [[RLMCollectionChange alloc] initWithChanges:changes], nil); - } - }; - - return [[RLMCancellationToken alloc] initWithToken:collection.add_notification_callback(cb) - realm:(RLMRealm *)[objcCollection realm]]; -} - -// Explicitly instantiate the templated function for the two types we'll use it on -template RLMNotificationToken *RLMAddNotificationBlock(id, realm::List&, void (^)(id, RLMCollectionChange *, NSError *), bool); -template RLMNotificationToken *RLMAddNotificationBlock(id, realm::Results&, void (^)(id, RLMCollectionChange *, NSError *), bool); diff --git a/Example/Pods/Realm/Realm/RLMConstants.m b/Example/Pods/Realm/Realm/RLMConstants.m deleted file mode 100644 index 7136127..0000000 --- a/Example/Pods/Realm/Realm/RLMConstants.m +++ /dev/null @@ -1,34 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -RLMNotification const RLMRealmRefreshRequiredNotification = @"RLMRealmRefreshRequiredNotification"; -RLMNotification const RLMRealmDidChangeNotification = @"RLMRealmDidChangeNotification"; - -NSString * const RLMErrorDomain = @"io.realm"; - -NSString * const RLMUnknownSystemErrorDomain = @"io.realm.unknown"; - -NSString * const RLMExceptionName = @"RLMException"; - -NSString * const RLMRealmVersionKey = @"RLMRealmVersion"; - -NSString * const RLMRealmCoreVersionKey = @"RLMRealmCoreVersion"; - -NSString * const RLMInvalidatedKey = @"invalidated"; diff --git a/Example/Pods/Realm/Realm/RLMListBase.mm b/Example/Pods/Realm/Realm/RLMListBase.mm deleted file mode 100644 index 78cf91a..0000000 --- a/Example/Pods/Realm/Realm/RLMListBase.mm +++ /dev/null @@ -1,60 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 "RLMListBase.h" - -#import "RLMArray_Private.hpp" -#import "RLMObservation.hpp" - -@interface RLMArray (KVO) -- (NSArray *)objectsAtIndexes:(__unused NSIndexSet *)indexes; -@end - -@implementation RLMListBase { - std::unique_ptr _observationInfo; -} - -- (instancetype)initWithArray:(RLMArray *)array { - self = [super init]; - if (self) { - __rlmArray = array; - } - return self; -} - -- (id)valueForKey:(NSString *)key { - return [__rlmArray valueForKey:key]; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { - return [__rlmArray countByEnumeratingWithState:state objects:buffer count:len]; -} - -- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes { - return [__rlmArray objectsAtIndexes:indexes]; -} - -- (void)addObserver:(id)observer - forKeyPath:(NSString *)keyPath - options:(NSKeyValueObservingOptions)options - context:(void *)context { - RLMEnsureArrayObservationInfo(_observationInfo, keyPath, __rlmArray, self); - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMMigration.mm b/Example/Pods/Realm/Realm/RLMMigration.mm deleted file mode 100644 index 6d8da01..0000000 --- a/Example/Pods/Realm/Realm/RLMMigration.mm +++ /dev/null @@ -1,162 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMMigration_Private.h" - -#import "RLMAccessor.h" -#import "RLMObject_Private.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMProperty_Private.h" -#import "RLMRealm_Dynamic.h" -#import "RLMRealm_Private.hpp" -#import "RLMResults_Private.h" -#import "RLMSchema_Private.hpp" -#import "RLMUtil.hpp" - -#import "object_store.hpp" -#import "shared_realm.hpp" -#import "schema.hpp" - -#import - -using namespace realm; - -// The source realm for a migration has to use a SharedGroup to be able to share -// the file with the destination realm, but we don't want to let the user call -// beginWriteTransaction on it as that would make no sense. -@interface RLMMigrationRealm : RLMRealm -@end - -@implementation RLMMigrationRealm -- (BOOL)readonly { - return YES; -} - -- (void)beginWriteTransaction { - @throw RLMException(@"Cannot modify the source Realm in a migration"); -} -@end - -@implementation RLMMigration { - realm::Schema *_schema; -} - -- (instancetype)initWithRealm:(RLMRealm *)realm oldRealm:(RLMRealm *)oldRealm schema:(realm::Schema &)schema { - self = [super init]; - if (self) { - _realm = realm; - _oldRealm = oldRealm; - _schema = &schema; - object_setClass(_oldRealm, RLMMigrationRealm.class); - } - return self; -} - -- (RLMSchema *)oldSchema { - return self.oldRealm.schema; -} - -- (RLMSchema *)newSchema { - return self.realm.schema; -} - -- (void)enumerateObjects:(NSString *)className block:(RLMObjectMigrationBlock)block { - // get all objects - RLMResults *objects = [_realm.schema schemaForClassName:className] ? [_realm allObjects:className] : nil; - RLMResults *oldObjects = [_oldRealm.schema schemaForClassName:className] ? [_oldRealm allObjects:className] : nil; - - if (objects && oldObjects) { - for (long i = oldObjects.count - 1; i >= 0; i--) { - @autoreleasepool { - block(oldObjects[i], objects[i]); - } - } - } - else if (objects) { - for (long i = objects.count - 1; i >= 0; i--) { - @autoreleasepool { - block(nil, objects[i]); - } - } - } - else if (oldObjects) { - for (long i = oldObjects.count - 1; i >= 0; i--) { - @autoreleasepool { - block(oldObjects[i], nil); - } - } - } -} - -- (void)execute:(RLMMigrationBlock)block { - @autoreleasepool { - // disable all primary keys for migration and use DynamicObject for all types - for (RLMObjectSchema *objectSchema in _realm.schema.objectSchema) { - objectSchema.accessorClass = RLMDynamicObject.class; - objectSchema.primaryKeyProperty.isPrimary = NO; - } - for (RLMObjectSchema *objectSchema in _oldRealm.schema.objectSchema) { - objectSchema.accessorClass = RLMDynamicObject.class; - } - - block(self, _oldRealm->_realm->schema_version()); - - _oldRealm = nil; - _realm = nil; - } -} - -- (RLMObject *)createObject:(NSString *)className withValue:(id)value { - return [_realm createObject:className withValue:value]; -} - -- (RLMObject *)createObject:(NSString *)className withObject:(id)object { - return [self createObject:className withValue:object]; -} - -- (void)deleteObject:(RLMObject *)object { - [_realm deleteObject:object]; -} - -- (BOOL)deleteDataForClassName:(NSString *)name { - if (!name) { - return false; - } - - TableRef table = ObjectStore::table_for_object_type(_realm.group, name.UTF8String); - if (!table) { - return false; - } - - if ([_realm.schema schemaForClassName:name]) { - table->clear(); - } - else { - realm::ObjectStore::delete_data_for_object(_realm.group, name.UTF8String); - } - - return true; -} - -- (void)renamePropertyForClass:(NSString *)className oldName:(NSString *)oldName newName:(NSString *)newName { - const char *objectType = className.UTF8String; - realm::ObjectStore::rename_property(_realm.group, *_schema, objectType, oldName.UTF8String, newName.UTF8String); -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMNetworkClient.m b/Example/Pods/Realm/Realm/RLMNetworkClient.m deleted file mode 100644 index ca8a156..0000000 --- a/Example/Pods/Realm/Realm/RLMNetworkClient.m +++ /dev/null @@ -1,229 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMNetworkClient.h" - -#import "RLMRealmConfiguration.h" -#import "RLMSyncErrorResponseModel.h" -#import "RLMSyncUtil_Private.h" - -typedef void(^RLMServerURLSessionCompletionBlock)(NSData *, NSURLResponse *, NSError *); - -static NSUInteger const kHTTPCodeRange = 100; - -typedef enum : NSUInteger { - Informational = 1, // 1XX - Success = 2, // 2XX - Redirection = 3, // 3XX - ClientError = 4, // 4XX - ServerError = 5, // 5XX -} RLMServerHTTPErrorCodeType; - -static NSRange RLM_rangeForErrorType(RLMServerHTTPErrorCodeType type) { - return NSMakeRange(type*100, kHTTPCodeRange); -} - -@implementation RLMNetworkClient - -+ (NSURLSession *)session { - return [NSURLSession sharedSession]; -} - -+ (NSURL *)urlForServer:(NSURL *)serverURL endpoint:(RLMServerEndpoint)endpoint { - NSString *pathComponent = nil; - switch (endpoint) { - case RLMServerEndpointAuth: - pathComponent = @"auth"; - break; - case RLMServerEndpointLogout: - // TODO: fix this - pathComponent = @"logout"; - NSAssert(NO, @"logout endpoint isn't implemented yet, don't use it"); - break; - case RLMServerEndpointAddCredentials: - // TODO: fix this - pathComponent = @"addCredentials"; - NSAssert(NO, @"add credentials endpoint isn't implemented yet, don't use it"); - break; - case RLMServerEndpointRemoveCredentials: - // TODO: fix this - pathComponent = @"removeCredentials"; - NSAssert(NO, @"remove credentials endpoint isn't implemented yet, don't use it"); - break; - } - NSAssert(pathComponent != nil, @"Unrecognized value for RLMServerEndpoint enum"); - return [serverURL URLByAppendingPathComponent:pathComponent]; -} - -+ (void)postRequestToEndpoint:(RLMServerEndpoint)endpoint - server:(NSURL *)serverURL - JSON:(NSDictionary *)jsonDictionary - completion:(RLMSyncCompletionBlock)completionBlock { - static NSTimeInterval const defaultTimeout = 60; - [self postRequestToEndpoint:endpoint - server:serverURL - JSON:jsonDictionary - timeout:defaultTimeout - completion:completionBlock]; -} - -// FIXME: should completion argument also pass back the NSURLResponse and/or the raw data? -+ (void)postRequestToEndpoint:(RLMServerEndpoint)endpoint - server:(NSURL *)serverURL - JSON:(NSDictionary *)jsonDictionary - timeout:(NSTimeInterval)timeout - completion:(RLMSyncCompletionBlock)completionBlock { - - NSError *localError = nil; - - // Attempt to convert the JSON - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary - options:(NSJSONWritingOptions)0 - error:&localError]; - if (!jsonData) { - completionBlock(localError, nil); - return; - } - - // Create the request - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self urlForServer:serverURL endpoint:endpoint]]; - request.HTTPBody = jsonData; - request.HTTPMethod = @"POST"; - request.timeoutInterval = MAX(timeout, 10); - [request addValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"]; - [request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; - - RLMServerURLSessionCompletionBlock handler = ^(NSData *data, - NSURLResponse *response, - NSError *error) { - if (error != nil) { - // Network error - completionBlock(error, nil); - return; - } - - NSError *localError = nil; - - if (![self validateResponse:response data:data error:&localError]) { - // Response error - completionBlock(localError, nil); - return; - } - - // Parse out the JSON - id json = [NSJSONSerialization JSONObjectWithData:data - options:(NSJSONReadingOptions)0 - error:&localError]; - if (!json || localError) { - // JSON parsing error - completionBlock(localError, nil); - } else if (![json isKindOfClass:[NSDictionary class]]) { - // JSON response malformed - localError = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - completionBlock(localError, nil); - } else { - // JSON parsed successfully - completionBlock(nil, (NSDictionary *)json); - } - }; - - // Add the request to a task and start it - NSURLSessionTask *task = [self.session dataTaskWithRequest:request - completionHandler:handler]; - [task resume]; -} - -+ (BOOL)validateResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error { - __autoreleasing NSError *localError = nil; - if (!error) { - error = &localError; - } - - if (![response isKindOfClass:[NSHTTPURLResponse class]]) { - // FIXME: Provide error message - *error = [NSError errorWithDomain:RLMSyncErrorDomain code:RLMSyncErrorBadResponse userInfo:nil]; - return NO; - } - - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - BOOL badResponse = (NSLocationInRange(httpResponse.statusCode, RLM_rangeForErrorType(ClientError)) - || NSLocationInRange(httpResponse.statusCode, RLM_rangeForErrorType(ServerError))); - if (badResponse) { - NSError *responseError = [self errorFromResponseData:data]; - if (responseError && responseError.userInfo[kRLMSyncErrorStatusCodeKey]) { - switch (responseError.code) { - case RLMSyncAuthErrorInvalidCredential: - case RLMSyncAuthErrorUserDoesNotExist: - case RLMSyncAuthErrorUserAlreadyExists: - // Authentication error - *error = responseError; - break; - - default: - // HTTP status error with some additional infor from the server - *error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorHTTPStatusCodeError - userInfo:responseError.userInfo]; - break; - } - } else { - // Fallback to HTTP status error without any additional info - *error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorHTTPStatusCodeError - userInfo:@{kRLMSyncErrorStatusCodeKey: @(httpResponse.statusCode)}]; - } - - return NO; - } - - if (!data) { - // FIXME: provide error message - *error = [NSError errorWithDomain:RLMSyncErrorDomain code:RLMSyncErrorBadResponse userInfo:nil]; - return NO; - } - - return YES; -} - -+ (NSError *)errorFromResponseData:(NSData *)data { - if (data.length == 0) { - return nil; - } - - id json = [NSJSONSerialization JSONObjectWithData:data - options:(NSJSONReadingOptions)0 - error:nil]; - if (!json || ![json isKindOfClass:[NSDictionary class]]) { - return nil; - } - - RLMSyncErrorResponseModel *responseModel = [[RLMSyncErrorResponseModel alloc] initWithDictionary:json]; - if (!responseModel) { - return nil; - } - - NSMutableDictionary *mutableUserInfo = [NSMutableDictionary dictionaryWithObject:@(responseModel.status) forKey:kRLMSyncErrorStatusCodeKey]; - [mutableUserInfo setValue:responseModel.title forKey:NSLocalizedDescriptionKey]; - [mutableUserInfo setValue:responseModel.hint forKey:NSLocalizedRecoverySuggestionErrorKey]; - - return [NSError errorWithDomain:RLMSyncErrorDomain code:responseModel.code userInfo:mutableUserInfo]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMObject.mm b/Example/Pods/Realm/Realm/RLMObject.mm deleted file mode 100644 index fb98d6c..0000000 --- a/Example/Pods/Realm/Realm/RLMObject.mm +++ /dev/null @@ -1,223 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObject_Private.hpp" - -#import "RLMAccessor.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMQueryUtil.hpp" -#import "RLMRealm_Private.hpp" -#import "RLMSchema_Private.h" - -// We declare things in RLMObject which are actually implemented in RLMObjectBase -// for documentation's sake, which leads to -Wunimplemented-method warnings. -// Other alternatives to this would be to disable -Wunimplemented-method for this -// file (but then we could miss legitimately missing things), or declaring the -// inherited things in a category (but they currently aren't nicely grouped for -// that). -@implementation RLMObject - -// synthesized in RLMObjectBase -@dynamic invalidated, realm, objectSchema; - -#pragma mark - Designated Initializers - -- (instancetype)init { - return [super init]; -} - -- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema { - return [super initWithValue:value schema:schema]; -} - -- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm schema:(RLMObjectSchema *)schema { - return [super initWithRealm:realm schema:schema]; -} - -#pragma mark - Convenience Initializers - -- (instancetype)initWithValue:(id)value { - [self.class sharedSchema]; // ensure this class' objectSchema is loaded in the partialSharedSchema - RLMSchema *schema = RLMSchema.partialSharedSchema; - return [super initWithValue:value schema:schema]; -} - -#pragma mark - Class-based Object Creation - -+ (instancetype)createInDefaultRealmWithValue:(id)value { - return (RLMObject *)RLMCreateObjectInRealmWithValue([RLMRealm defaultRealm], [self className], value, false); -} - -+ (instancetype)createInRealm:(RLMRealm *)realm withValue:(id)value { - return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, false); -} - -+ (instancetype)createOrUpdateInDefaultRealmWithValue:(id)value { - return [self createOrUpdateInRealm:[RLMRealm defaultRealm] withValue:value]; -} - -+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value { - // verify primary key - RLMObjectSchema *schema = [self sharedSchema]; - if (!schema.primaryKeyProperty) { - NSString *reason = [NSString stringWithFormat:@"'%@' does not have a primary key and can not be updated", schema.className]; - @throw [NSException exceptionWithName:@"RLMExecption" reason:reason userInfo:nil]; - } - return (RLMObject *)RLMCreateObjectInRealmWithValue(realm, [self className], value, true); -} - -#pragma mark - Subscripting - -- (id)objectForKeyedSubscript:(NSString *)key { - return RLMObjectBaseObjectForKeyedSubscript(self, key); -} - -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { - RLMObjectBaseSetObjectForKeyedSubscript(self, key, obj); -} - -#pragma mark - Getting & Querying - -+ (RLMResults *)allObjects { - return RLMGetObjects(RLMRealm.defaultRealm, self.className, nil); -} - -+ (RLMResults *)allObjectsInRealm:(RLMRealm *)realm { - return RLMGetObjects(realm, self.className, nil); -} - -+ (RLMResults *)objectsWhere:(NSString *)predicateFormat, ... { - va_list args; - va_start(args, predicateFormat); - RLMResults *results = [self objectsWhere:predicateFormat args:args]; - va_end(args); - return results; -} - -+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args { - return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]]; -} - -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ... { - va_list args; - va_start(args, predicateFormat); - RLMResults *results = [self objectsInRealm:realm where:predicateFormat args:args]; - va_end(args); - return results; -} - -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args { - return [self objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]]; -} - -+ (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate { - return RLMGetObjects(RLMRealm.defaultRealm, self.className, predicate); -} - -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(NSPredicate *)predicate { - return RLMGetObjects(realm, self.className, predicate); -} - -+ (instancetype)objectForPrimaryKey:(id)primaryKey { - return RLMGetObject(RLMRealm.defaultRealm, self.className, primaryKey); -} - -+ (instancetype)objectInRealm:(RLMRealm *)realm forPrimaryKey:(id)primaryKey { - return RLMGetObject(realm, self.className, primaryKey); -} - -#pragma mark - Other Instance Methods - -- (BOOL)isEqualToObject:(RLMObject *)object { - return [object isKindOfClass:RLMObject.class] && RLMObjectBaseAreEqual(self, object); -} - -+ (NSString *)className { - return [super className]; -} - -#pragma mark - Default values for schema definition - -+ (NSArray *)indexedProperties { - return @[]; -} - -+ (NSDictionary *)linkingObjectsProperties { - return @{}; -} - -+ (NSDictionary *)defaultPropertyValues { - return nil; -} - -+ (NSString *)primaryKey { - return nil; -} - -+ (NSArray *)ignoredProperties { - return nil; -} - -+ (NSArray *)requiredProperties { - return @[]; -} - -@end - -@implementation RLMDynamicObject - -+ (BOOL)shouldIncludeInDefaultSchema { - return NO; -} - -- (id)valueForUndefinedKey:(NSString *)key { - return RLMDynamicGetByName(self, key, false); -} - -- (void)setValue:(id)value forUndefinedKey:(NSString *)key { - RLMDynamicValidatedSet(self, key, value); -} - -@end - -@implementation RLMWeakObjectHandle { - realm::Row _row; - RLMClassInfo *_info; - Class _objectClass; -} - -- (instancetype)initWithObject:(RLMObjectBase *)object { - if (!(self = [super init])) { - return nil; - } - - _row = object->_row; - _info = object->_info; - _objectClass = object.class; - - return self; -} - -- (RLMObjectBase *)object { - RLMObjectBase *object = RLMCreateManagedAccessor(_objectClass, _info->realm, _info); - object->_row = std::move(_row); - return object; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMObjectBase.mm b/Example/Pods/Realm/Realm/RLMObjectBase.mm deleted file mode 100644 index c3e23c8..0000000 --- a/Example/Pods/Realm/Realm/RLMObjectBase.mm +++ /dev/null @@ -1,454 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObject_Private.hpp" - -#import "RLMAccessor.h" -#import "RLMArray_Private.hpp" -#import "RLMListBase.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObservation.hpp" -#import "RLMOptionalBase.h" -#import "RLMProperty_Private.h" -#import "RLMRealm_Private.hpp" -#import "RLMSchema_Private.h" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -using namespace realm; - -const NSUInteger RLMDescriptionMaxDepth = 5; - -static bool maybeInitObjectSchemaForUnmanaged(RLMObjectBase *obj) { - obj->_objectSchema = [obj.class sharedSchema]; - if (!obj->_objectSchema) { - return false; - } - - // set default values - if (!obj->_objectSchema.isSwiftClass) { - NSDictionary *dict = RLMDefaultValuesForObjectSchema(obj->_objectSchema); - for (NSString *key in dict) { - [obj setValue:dict[key] forKey:key]; - } - } - - // set unmanaged accessor class - object_setClass(obj, obj->_objectSchema.unmanagedClass); - return true; -} - -@implementation RLMObjectBase -// unmanaged init -- (instancetype)init { - if ((self = [super init])) { - maybeInitObjectSchemaForUnmanaged(self); - } - return self; -} - -- (void)dealloc { - // This can't be a unique_ptr because associated objects are removed - // *after* c++ members are destroyed and dealloc is called, and we need it - // to be in a validish state when that happens - delete _observationInfo; - _observationInfo = nullptr; -} - -static id validatedObjectForProperty(id obj, RLMProperty *prop, RLMSchema *schema) { - if (RLMIsObjectValidForProperty(obj, prop)) { - return obj; - } - - // check for object or array of properties - if (prop.type == RLMPropertyTypeObject) { - // for object create and try to initialize with obj - RLMObjectSchema *objSchema = schema[prop.objectClassName]; - return [[objSchema.objectClass alloc] initWithValue:obj schema:schema]; - } - else if (prop.type == RLMPropertyTypeArray && [obj conformsToProtocol:@protocol(NSFastEnumeration)]) { - // for arrays, create objects for each element and return new array - RLMObjectSchema *objSchema = schema[prop.objectClassName]; - RLMArray *objects = [[RLMArray alloc] initWithObjectClassName:objSchema.className]; - for (id el in obj) { - [objects addObject:[[objSchema.objectClass alloc] initWithValue:el schema:schema]]; - } - return objects; - } - - // if not convertible to prop throw - @throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name); -} - -- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema { - if (!(self = [super init])) { - return self; - } - - if (!maybeInitObjectSchemaForUnmanaged(self)) { - // Don't populate fields from the passed-in object if we're called - // during schema init - return self; - } - - NSArray *properties = _objectSchema.properties; - if (NSArray *array = RLMDynamicCast(value)) { - if (array.count != properties.count) { - @throw RLMException(@"Invalid array input. Number of array elements does not match number of properties."); - } - for (NSUInteger i = 0; i < array.count; i++) { - id propertyValue = validatedObjectForProperty(array[i], properties[i], schema); - [self setValue:RLMCoerceToNil(propertyValue) forKeyPath:[properties[i] name]]; - } - } - else if (value) { - // assume our object is an NSDictionary or an object with kvc properties - NSDictionary *defaultValues = nil; - for (RLMProperty *prop in properties) { - id obj = RLMValidatedValueForProperty(value, prop.name, _objectSchema.className); - - // get default for nil object - if (!obj) { - if (!defaultValues) { - defaultValues = RLMDefaultValuesForObjectSchema(_objectSchema); - } - obj = defaultValues[prop.name]; - } - - // don't set unspecified properties - if (!obj) { - continue; - } - - obj = validatedObjectForProperty(obj, prop, schema); - [self setValue:RLMCoerceToNil(obj) forKeyPath:prop.name]; - } - } else { - @throw RLMException(@"Must provide a non-nil value."); - } - - return self; -} - -id RLMCreateManagedAccessor(Class cls, __unsafe_unretained RLMRealm *realm, RLMClassInfo *info) { - RLMObjectBase *obj = [[cls alloc] initWithRealm:realm schema:info->rlmObjectSchema]; - obj->_info = info; - return obj; -} - -- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm - schema:(RLMObjectSchema *)schema { - self = [super init]; - if (self) { - _realm = realm; - _objectSchema = schema; - } - return self; -} - -- (id)valueForKey:(NSString *)key { - if (_observationInfo) { - return _observationInfo->valueForKey(key); - } - return [super valueForKey:key]; -} - -// Generic Swift properties can't be dynamic, so KVO doesn't work for them by default -- (id)valueForUndefinedKey:(NSString *)key { - if (Ivar ivar = _objectSchema[key].swiftIvar) { - return RLMCoerceToNil(object_getIvar(self, ivar)); - } - return [super valueForUndefinedKey:key]; -} - -- (void)setValue:(id)value forUndefinedKey:(NSString *)key { - RLMProperty *property = _objectSchema[key]; - if (Ivar ivar = property.swiftIvar) { - if (property.type == RLMPropertyTypeArray && [value conformsToProtocol:@protocol(NSFastEnumeration)]) { - RLMArray *array = [object_getIvar(self, ivar) _rlmArray]; - [array removeAllObjects]; - [array addObjects:value]; - } - else if (property.optional) { - RLMOptionalBase *optional = object_getIvar(self, ivar); - optional.underlyingValue = value; - } - return; - } - [super setValue:value forUndefinedKey:key]; -} - -// overridden at runtime per-class for performance -+ (NSString *)className { - NSString *className = NSStringFromClass(self); - if ([RLMSwiftSupport isSwiftClassName:className]) { - className = [RLMSwiftSupport demangleClassName:className]; - } - return className; -} - -// overridden at runtime per-class for performance -+ (RLMObjectSchema *)sharedSchema { - return [RLMSchema sharedSchemaForClass:self.class]; -} - -+ (Class)objectUtilClass:(BOOL)isSwift { - return RLMObjectUtilClass(isSwift); -} - -- (NSString *)description -{ - if (self.isInvalidated) { - return @"[invalid object]"; - } - - return [self descriptionWithMaxDepth:RLMDescriptionMaxDepth]; -} - -- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth { - if (depth == 0) { - return @""; - } - - NSString *baseClassName = _objectSchema.className; - NSMutableString *mString = [NSMutableString stringWithFormat:@"%@ {\n", baseClassName]; - - for (RLMProperty *property in _objectSchema.properties) { - id object = RLMObjectBaseObjectForKeyedSubscript(self, property.name); - NSString *sub; - if ([object respondsToSelector:@selector(descriptionWithMaxDepth:)]) { - sub = [object descriptionWithMaxDepth:depth - 1]; - } - else if (property.type == RLMPropertyTypeData) { - static NSUInteger maxPrintedDataLength = 24; - NSData *data = object; - NSUInteger length = data.length; - if (length > maxPrintedDataLength) { - data = [NSData dataWithBytes:data.bytes length:maxPrintedDataLength]; - } - NSString *dataDescription = [data description]; - sub = [NSString stringWithFormat:@"<%@ — %lu total bytes>", [dataDescription substringWithRange:NSMakeRange(1, dataDescription.length - 2)], (unsigned long)length]; - } - else { - sub = [object description]; - } - [mString appendFormat:@"\t%@ = %@;\n", property.name, [sub stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]]; - } - [mString appendString:@"}"]; - - return [NSString stringWithString:mString]; -} - -- (RLMRealm *)realm { - return _realm; -} - -- (RLMObjectSchema *)objectSchema { - return _objectSchema; -} - -- (BOOL)isInvalidated { - // if not unmanaged and our accessor has been detached, we have been deleted - return self.class == _objectSchema.accessorClass && !_row.is_attached(); -} - -- (BOOL)isEqual:(id)object { - if (RLMObjectBase *other = RLMDynamicCast(object)) { - if (_objectSchema.primaryKeyProperty) { - return RLMObjectBaseAreEqual(self, other); - } - } - return [super isEqual:object]; -} - -- (NSUInteger)hash { - if (_objectSchema.primaryKeyProperty) { - id primaryProperty = [self valueForKey:_objectSchema.primaryKeyProperty.name]; - - // modify the hash of our primary key value to avoid potential (although unlikely) collisions - return [primaryProperty hash] ^ 1; - } - else { - return [super hash]; - } -} - -+ (BOOL)shouldIncludeInDefaultSchema { - return RLMIsObjectSubclass(self); -} - -+ (NSString *)_realmObjectName { - return nil; -} - -- (id)mutableArrayValueForKey:(NSString *)key { - id obj = [self valueForKey:key]; - if ([obj isKindOfClass:[RLMArray class]]) { - return obj; - } - return [super mutableArrayValueForKey:key]; -} - -- (void)addObserver:(id)observer - forKeyPath:(NSString *)keyPath - options:(NSKeyValueObservingOptions)options - context:(void *)context { - if (!_observationInfo) { - _observationInfo = new RLMObservationInfo(self); - } - _observationInfo->recordObserver(_row, _info, _objectSchema, keyPath); - - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath { - [super removeObserver:observer forKeyPath:keyPath]; - if (_observationInfo) - _observationInfo->removeObserver(); -} - -+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { - const char *className = class_getName(self); - const char accessorClassPrefix[] = "RLMAccessor_"; - if (!strncmp(className, accessorClassPrefix, sizeof(accessorClassPrefix) - 1)) { - if (self.sharedSchema[key]) { - return NO; - } - } - - return [super automaticallyNotifiesObserversForKey:key]; -} - -@end - -RLMRealm *RLMObjectBaseRealm(__unsafe_unretained RLMObjectBase *object) { - return object ? object->_realm : nil; -} - -RLMObjectSchema *RLMObjectBaseObjectSchema(__unsafe_unretained RLMObjectBase *object) { - return object ? object->_objectSchema : nil; -} - -id RLMObjectBaseObjectForKeyedSubscript(RLMObjectBase *object, NSString *key) { - if (!object) { - return nil; - } - - if (object->_realm) { - return RLMDynamicGetByName(object, key, false); - } - else { - return [object valueForKey:key]; - } -} - -void RLMObjectBaseSetObjectForKeyedSubscript(RLMObjectBase *object, NSString *key, id obj) { - if (!object) { - return; - } - - if (object->_realm) { - RLMDynamicValidatedSet(object, key, obj); - } - else { - [object setValue:obj forKey:key]; - } -} - - -BOOL RLMObjectBaseAreEqual(RLMObjectBase *o1, RLMObjectBase *o2) { - // if not the correct types throw - if ((o1 && ![o1 isKindOfClass:RLMObjectBase.class]) || (o2 && ![o2 isKindOfClass:RLMObjectBase.class])) { - @throw RLMException(@"Can only compare objects of class RLMObjectBase"); - } - // if identical object (or both are nil) - if (o1 == o2) { - return YES; - } - // if one is nil - if (o1 == nil || o2 == nil) { - return NO; - } - // if not in realm or differing realms - if (o1->_realm == nil || o1->_realm != o2->_realm) { - return NO; - } - // if either are detached - if (!o1->_row.is_attached() || !o2->_row.is_attached()) { - return NO; - } - // if table and index are the same - return o1->_row.get_table() == o2->_row.get_table() - && o1->_row.get_index() == o2->_row.get_index(); -} - -id RLMValidatedValueForProperty(id object, NSString *key, NSString *className) { - @try { - return [object valueForKey:key]; - } - @catch (NSException *e) { - if ([e.name isEqualToString:NSUndefinedKeyException]) { - @throw RLMException(@"Invalid value '%@' to initialize object of type '%@': missing key '%@'", - object, className, key); - } - @throw; - } -} - -Class RLMObjectUtilClass(BOOL isSwift) { - static Class objectUtilObjc = [RLMObjectUtil class]; - static Class objectUtilSwift = NSClassFromString(@"RealmSwiftObjectUtil"); - return isSwift && objectUtilSwift ? objectUtilSwift : objectUtilObjc; -} - -@implementation RLMObjectUtil - -+ (NSArray *)ignoredPropertiesForClass:(Class)cls { - return [cls ignoredProperties]; -} - -+ (NSArray *)indexedPropertiesForClass:(Class)cls { - return [cls indexedProperties]; -} - -+ (NSDictionary *)linkingObjectsPropertiesForClass:(Class)cls { - return [cls linkingObjectsProperties]; -} - -+ (NSDictionary *)linkingObjectProperties:(__unused id)object { - return nil; -} - -+ (NSArray *)getGenericListPropertyNames:(__unused id)obj { - return nil; -} - -+ (NSDictionary *)getLinkingObjectsProperties:(__unused id)obj { - return nil; -} - -+ (NSDictionary *)getOptionalProperties:(__unused id)obj { - return nil; -} - -+ (NSArray *)requiredPropertiesForClass:(Class)cls { - return [cls requiredProperties]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMObjectSchema.mm b/Example/Pods/Realm/Realm/RLMObjectSchema.mm deleted file mode 100644 index fb19575..0000000 --- a/Example/Pods/Realm/Realm/RLMObjectSchema.mm +++ /dev/null @@ -1,444 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObjectSchema_Private.hpp" - -#import "RLMArray.h" -#import "RLMListBase.h" -#import "RLMObject_Private.h" -#import "RLMProperty_Private.hpp" -#import "RLMRealm_Dynamic.h" -#import "RLMRealm_Private.hpp" -#import "RLMSchema_Private.h" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -#import "object_store.hpp" - -using namespace realm; - -// private properties -@interface RLMObjectSchema () -@property (nonatomic, readwrite) NSDictionary *allPropertiesByName; -@property (nonatomic, readwrite) NSString *className; -@end - -@implementation RLMObjectSchema { - NSArray *_swiftGenericProperties; -} - -- (instancetype)initWithClassName:(NSString *)objectClassName objectClass:(Class)objectClass properties:(NSArray *)properties { - self = [super init]; - self.className = objectClassName; - self.properties = properties; - self.objectClass = objectClass; - self.accessorClass = objectClass; - self.unmanagedClass = objectClass; - return self; -} - -// return properties by name -- (RLMProperty *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)key { - return _allPropertiesByName[key]; -} - -// create property map when setting property array -- (void)setProperties:(NSArray *)properties { - _properties = properties; - [self _propertiesDidChange]; -} - -- (void)setComputedProperties:(NSArray *)computedProperties { - _computedProperties = computedProperties; - [self _propertiesDidChange]; -} - -- (void)_propertiesDidChange { - NSMutableDictionary *map = [NSMutableDictionary dictionaryWithCapacity:_properties.count + _computedProperties.count]; - NSUInteger index = 0; - for (RLMProperty *prop in _properties) { - prop.index = index++; - map[prop.name] = prop; - if (prop.isPrimary) { - self.primaryKeyProperty = prop; - } - } - for (RLMProperty *prop in _computedProperties) { - map[prop.name] = prop; - } - _allPropertiesByName = map; -} - - -- (void)setPrimaryKeyProperty:(RLMProperty *)primaryKeyProperty { - _primaryKeyProperty.isPrimary = NO; - primaryKeyProperty.isPrimary = YES; - _primaryKeyProperty = primaryKeyProperty; -} - -+ (instancetype)schemaForObjectClass:(Class)objectClass { - RLMObjectSchema *schema = [RLMObjectSchema new]; - - // determine classname from objectclass as className method has not yet been updated - NSString *className = NSStringFromClass(objectClass); - bool isSwift = [RLMSwiftSupport isSwiftClassName:className]; - if (isSwift) { - className = [RLMSwiftSupport demangleClassName:className]; - } - schema.className = className; - schema.objectClass = objectClass; - schema.accessorClass = objectClass; - schema.isSwiftClass = isSwift; - - // create array of RLMProperties, inserting properties of superclasses first - Class cls = objectClass; - Class superClass = class_getSuperclass(cls); - NSArray *allProperties = @[]; - while (superClass && superClass != RLMObjectBase.class) { - allProperties = [[RLMObjectSchema propertiesForClass:cls isSwift:isSwift] arrayByAddingObjectsFromArray:allProperties]; - cls = superClass; - superClass = class_getSuperclass(superClass); - } - NSArray *persistedProperties = [allProperties filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(RLMProperty *property, NSDictionary *) { - return !RLMPropertyTypeIsComputed(property.type); - }]]; - schema.properties = persistedProperties; - - NSArray *computedProperties = [allProperties filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(RLMProperty *property, NSDictionary *) { - return RLMPropertyTypeIsComputed(property.type); - }]]; - schema.computedProperties = computedProperties; - - // verify that we didn't add any properties twice due to inheritance - if (allProperties.count != [NSSet setWithArray:[allProperties valueForKey:@"name"]].count) { - NSCountedSet *countedPropertyNames = [NSCountedSet setWithArray:[allProperties valueForKey:@"name"]]; - NSSet *duplicatePropertyNames = [countedPropertyNames filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *) { - return [countedPropertyNames countForObject:object] > 1; - }]]; - - if (duplicatePropertyNames.count == 1) { - @throw RLMException(@"Property '%@' is declared multiple times in the class hierarchy of '%@'", duplicatePropertyNames.allObjects.firstObject, className); - } else { - @throw RLMException(@"Object '%@' has properties that are declared multiple times in its class hierarchy: '%@'", className, [duplicatePropertyNames.allObjects componentsJoinedByString:@"', '"]); - } - } - - if (NSString *primaryKey = [objectClass primaryKey]) { - for (RLMProperty *prop in schema.properties) { - if ([primaryKey isEqualToString:prop.name]) { - prop.indexed = YES; - schema.primaryKeyProperty = prop; - break; - } - } - - if (!schema.primaryKeyProperty) { - @throw RLMException(@"Primary key property '%@' does not exist on object '%@'", primaryKey, className); - } - if (schema.primaryKeyProperty.type != RLMPropertyTypeInt && schema.primaryKeyProperty.type != RLMPropertyTypeString) { - @throw RLMException(@"Only 'string' and 'int' properties can be designated the primary key"); - } - } - - for (RLMProperty *prop in schema.properties) { - if (prop.optional && !RLMPropertyTypeIsNullable(prop.type)) { - @throw RLMException(@"Only 'string', 'binary', and 'object' properties can be made optional, and property '%@' is of type '%@'.", - prop.name, RLMTypeToString(prop.type)); - } - } - - return schema; -} - -+ (nullable NSString *)baseNameForLazySwiftProperty:(NSString *)propertyName { - // A Swift lazy var shows up as two separate children on the reflection tree: one named 'x', and another that is - // optional and is named 'x.storage'. Note that '.' is illegal in either a Swift or Objective-C property name. - NSString *const storageSuffix = @".storage"; - if ([propertyName hasSuffix:storageSuffix]) { - return [propertyName substringToIndex:propertyName.length - storageSuffix.length]; - } - return nil; -} - -+ (NSArray *)propertiesForClass:(Class)objectClass isSwift:(bool)isSwiftClass { - Class objectUtil = [objectClass objectUtilClass:isSwiftClass]; - NSArray *ignoredProperties = [objectUtil ignoredPropertiesForClass:objectClass]; - NSDictionary *linkingObjectsProperties = [objectUtil linkingObjectsPropertiesForClass:objectClass]; - - // For Swift classes we need an instance of the object when parsing properties - id swiftObjectInstance = isSwiftClass ? [[objectClass alloc] init] : nil; - - unsigned int count; - objc_property_t *props = class_copyPropertyList(objectClass, &count); - NSMutableArray *propArray = [NSMutableArray arrayWithCapacity:count]; - NSSet *indexed = [[NSSet alloc] initWithArray:[objectUtil indexedPropertiesForClass:objectClass]]; - for (unsigned int i = 0; i < count; i++) { - NSString *propertyName = @(property_getName(props[i])); - if ([ignoredProperties containsObject:propertyName]) { - continue; - } - - RLMProperty *prop = nil; - if (isSwiftClass) { - prop = [[RLMProperty alloc] initSwiftPropertyWithName:propertyName - indexed:[indexed containsObject:propertyName] - linkPropertyDescriptor:linkingObjectsProperties[propertyName] - property:props[i] - instance:swiftObjectInstance]; - } - else { - prop = [[RLMProperty alloc] initWithName:propertyName - indexed:[indexed containsObject:propertyName] - linkPropertyDescriptor:linkingObjectsProperties[propertyName] - property:props[i]]; - } - - if (prop) { - [propArray addObject:prop]; - } - } - free(props); - - if (isSwiftClass) { - // List<> properties don't show up as objective-C properties due to - // being generic, so use Swift reflection to get a list of them, and - // then access their ivars directly - for (NSString *propName in [objectUtil getGenericListPropertyNames:swiftObjectInstance]) { - Ivar ivar = class_getInstanceVariable(objectClass, propName.UTF8String); - id value = object_getIvar(swiftObjectInstance, ivar); - NSString *className = [value _rlmArray].objectClassName; - NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) { - return [obj.name isEqualToString:propName]; - }]; - if (existing != NSNotFound) { - [propArray removeObjectAtIndex:existing]; - } - [propArray addObject:[[RLMProperty alloc] initSwiftListPropertyWithName:propName - ivar:ivar - objectClassName:className]]; - } - - // Ditto for LinkingObjects<> properties. - NSDictionary *linkingObjectsProperties = [objectUtil getLinkingObjectsProperties:swiftObjectInstance]; - for (NSString *propName in linkingObjectsProperties) { - NSDictionary *info = linkingObjectsProperties[propName]; - Ivar ivar = class_getInstanceVariable(objectClass, propName.UTF8String); - - NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) { - return [obj.name isEqualToString:propName]; - }]; - if (existing != NSNotFound) { - [propArray removeObjectAtIndex:existing]; - } - - [propArray addObject:[[RLMProperty alloc] initSwiftLinkingObjectsPropertyWithName:propName - ivar:ivar - objectClassName:info[@"class"] - linkOriginPropertyName:info[@"property"]]]; - } - } - - if (auto optionalProperties = [objectUtil getOptionalProperties:swiftObjectInstance]) { - for (RLMProperty *property in propArray) { - property.optional = false; - } - [optionalProperties enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSNumber *propertyType, __unused BOOL *stop) { - if ([ignoredProperties containsObject:propertyName]) { - return; - } - NSUInteger existing = [propArray indexOfObjectPassingTest:^BOOL(RLMProperty *obj, __unused NSUInteger idx, __unused BOOL *stop) { - return [obj.name isEqualToString:propertyName]; - }]; - RLMProperty *property; - if (existing != NSNotFound) { - property = propArray[existing]; - property.optional = true; - } - if (auto type = RLMCoerceToNil(propertyType)) { - if (existing == NSNotFound) { - // Check to see if this optional property is an underlying storage property for a Swift lazy var. - // Managed lazy vars are't allowed. - // NOTE: Revisit this once property behaviors are implemented in Swift. - if (NSString *lazyPropertyBaseName = [self baseNameForLazySwiftProperty:propertyName]) { - if ([ignoredProperties containsObject:lazyPropertyBaseName]) { - // This property is the storage property for a ignored lazy Swift property. Just continue. - return; - } else { - @throw RLMException(@"Lazy managed property '%@' is not allowed on a Realm Swift object class. Either add the property to the ignored properties list or make it non-lazy.", lazyPropertyBaseName); - } - } - // The current property isn't a storage property for a lazy Swift property. - property = [[RLMProperty alloc] initSwiftOptionalPropertyWithName:propertyName - indexed:[indexed containsObject:propertyName] - ivar:class_getInstanceVariable(objectClass, propertyName.UTF8String) - propertyType:RLMPropertyType(type.intValue)]; - [propArray addObject:property]; - } - else { - property.type = RLMPropertyType(type.intValue); - } - } - }]; - } - if (auto requiredProperties = [objectUtil requiredPropertiesForClass:objectClass]) { - for (RLMProperty *property in propArray) { - bool required = [requiredProperties containsObject:property.name]; - if (required && property.type == RLMPropertyTypeObject) { - @throw RLMException(@"Object properties cannot be made required, " - "but '+[%@ requiredProperties]' included '%@'", objectClass, property.name); - } - property.optional &= !required; - } - } - - for (RLMProperty *property in propArray) { - if (!property.optional && property.type == RLMPropertyTypeObject) { // remove if/when core supports required link columns - @throw RLMException(@"The `%@.%@` property must be marked as being optional.", [objectClass className], property.name); - } - } - - return propArray; -} - -- (id)copyWithZone:(NSZone *)zone { - RLMObjectSchema *schema = [[RLMObjectSchema allocWithZone:zone] init]; - schema->_objectClass = _objectClass; - schema->_className = _className; - schema->_objectClass = _objectClass; - schema->_accessorClass = _objectClass; - schema->_unmanagedClass = _unmanagedClass; - schema->_isSwiftClass = _isSwiftClass; - - // call property setter to reset map and primary key - schema.properties = [[NSArray allocWithZone:zone] initWithArray:_properties copyItems:YES]; - schema.computedProperties = [[NSArray allocWithZone:zone] initWithArray:_computedProperties copyItems:YES]; - - return schema; -} - -- (BOOL)isEqualToObjectSchema:(RLMObjectSchema *)objectSchema { - if (objectSchema.properties.count != _properties.count) { - return NO; - } - - if (![_properties isEqualToArray:objectSchema.properties]) { - return NO; - } - if (![_computedProperties isEqualToArray:objectSchema.computedProperties]) { - return NO; - } - - return YES; -} - -- (NSString *)description { - NSMutableString *propertiesString = [NSMutableString string]; - for (RLMProperty *property in self.properties) { - [propertiesString appendFormat:@"\t%@\n", [property.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]]; - } - for (RLMProperty *property in self.computedProperties) { - [propertiesString appendFormat:@"\t%@\n", [property.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]]; - } - return [NSString stringWithFormat:@"%@ {\n%@}", self.className, propertiesString]; -} - -- (NSString *)objectName { - return [self.objectClass _realmObjectName] ?: _className; -} - -- (realm::ObjectSchema)objectStoreCopy { - ObjectSchema objectSchema; - objectSchema.name = self.objectName.UTF8String; - objectSchema.primary_key = _primaryKeyProperty ? _primaryKeyProperty.name.UTF8String : ""; - for (RLMProperty *prop in _properties) { - Property p = [prop objectStoreCopy]; - p.is_primary = (prop == _primaryKeyProperty); - objectSchema.persisted_properties.push_back(std::move(p)); - } - for (RLMProperty *prop in _computedProperties) { - objectSchema.computed_properties.push_back([prop objectStoreCopy]); - } - return objectSchema; -} - -+ (instancetype)objectSchemaForObjectStoreSchema:(realm::ObjectSchema const&)objectSchema { - RLMObjectSchema *schema = [RLMObjectSchema new]; - schema.className = @(objectSchema.name.c_str()); - - // create array of RLMProperties - NSMutableArray *properties = [NSMutableArray arrayWithCapacity:objectSchema.persisted_properties.size()]; - for (const Property &prop : objectSchema.persisted_properties) { - RLMProperty *property = [RLMProperty propertyForObjectStoreProperty:prop]; - property.isPrimary = (prop.name == objectSchema.primary_key); - [properties addObject:property]; - } - schema.properties = properties; - - NSMutableArray *computedProperties = [NSMutableArray arrayWithCapacity:objectSchema.computed_properties.size()]; - for (const Property &prop : objectSchema.computed_properties) { - [computedProperties addObject:[RLMProperty propertyForObjectStoreProperty:prop]]; - } - schema.computedProperties = computedProperties; - - // get primary key from realm metadata - if (objectSchema.primary_key.length()) { - NSString *primaryKeyString = [NSString stringWithUTF8String:objectSchema.primary_key.c_str()]; - schema.primaryKeyProperty = schema[primaryKeyString]; - if (!schema.primaryKeyProperty) { - @throw RLMException(@"No property matching primary key '%@'", primaryKeyString); - } - } - - // for dynamic schema use vanilla RLMDynamicObject accessor classes - schema.objectClass = RLMObject.class; - schema.accessorClass = RLMDynamicObject.class; - schema.unmanagedClass = RLMObject.class; - - return schema; -} - -- (NSArray *)swiftGenericProperties { - if (_swiftGenericProperties) { - return _swiftGenericProperties; - } - - // This check isn't semantically required, but avoiding accessing the local - // static helps perf in the obj-c case - if (!_isSwiftClass) { - return _swiftGenericProperties = @[]; - } - - // Check if it's a swift class using the obj-c API - static Class s_swiftObjectClass = NSClassFromString(@"RealmSwiftObject"); - if (![_accessorClass isSubclassOfClass:s_swiftObjectClass]) { - return _swiftGenericProperties = @[]; - } - - NSMutableArray *genericProperties = [NSMutableArray new]; - for (RLMProperty *prop in _properties) { - if (prop->_swiftIvar) { - [genericProperties addObject:prop]; - } - } - // Currently all computed properties are Swift generics - [genericProperties addObjectsFromArray:_computedProperties]; - - return _swiftGenericProperties = genericProperties; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMObjectStore.mm b/Example/Pods/Realm/Realm/RLMObjectStore.mm deleted file mode 100644 index 144748c..0000000 --- a/Example/Pods/Realm/Realm/RLMObjectStore.mm +++ /dev/null @@ -1,550 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObjectStore.h" - -#import "RLMAccessor.h" -#import "RLMArray_Private.hpp" -#import "RLMListBase.h" -#import "RLMObservation.hpp" -#import "RLMObject_Private.hpp" -#import "RLMObjectSchema_Private.hpp" -#import "RLMOptionalBase.h" -#import "RLMProperty_Private.h" -#import "RLMQueryUtil.hpp" -#import "RLMRealm_Private.hpp" -#import "RLMSchema_Private.h" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -#import "object_store.hpp" -#import "results.hpp" -#import "shared_realm.hpp" - -#import - -using namespace realm; - -void RLMRealmCreateAccessors(RLMSchema *schema) { - for (RLMObjectSchema *objectSchema in schema.objectSchema) { - if (objectSchema.accessorClass != objectSchema.objectClass) { - continue; - } - - static unsigned long long count = 0; - NSString *prefix = [NSString stringWithFormat:@"RLMAccessor_%llu_", count++]; - objectSchema.accessorClass = RLMAccessorClassForObjectClass(objectSchema.objectClass, objectSchema, prefix); - } -} - -static inline void RLMVerifyRealmRead(__unsafe_unretained RLMRealm *const realm) { - if (!realm) { - @throw RLMException(@"Realm must not be nil"); - } - [realm verifyThread]; -} - -static inline void RLMVerifyInWriteTransaction(__unsafe_unretained RLMRealm *const realm) { - RLMVerifyRealmRead(realm); - // if realm is not writable throw - if (!realm.inWriteTransaction) { - @throw RLMException(@"Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first."); - } -} - -void RLMInitializeSwiftAccessorGenerics(__unsafe_unretained RLMObjectBase *const object) { - if (!object || !object->_row || !object->_objectSchema->_isSwiftClass) { - return; - } - if (![object isKindOfClass:object->_objectSchema.objectClass]) { - // It can be a different class if it's a dynamic object, and those don't - // require any init here (and would crash since they don't have the ivars) - return; - } - - for (RLMProperty *prop in object->_objectSchema.swiftGenericProperties) { - if (prop->_type == RLMPropertyTypeArray) { - RLMArray *array = [[RLMArrayLinkView alloc] initWithParent:object property:prop]; - [object_getIvar(object, prop.swiftIvar) set_rlmArray:array]; - } - else if (prop.type == RLMPropertyTypeLinkingObjects) { - id linkingObjects = object_getIvar(object, prop.swiftIvar); - [linkingObjects setObject:(id)[[RLMWeakObjectHandle alloc] initWithObject:object]]; - [linkingObjects setProperty:prop]; - } - else { - RLMOptionalBase *optional = object_getIvar(object, prop.swiftIvar); - optional.property = prop; - optional.object = object; - } - } -} - -static void validateValueForProperty(__unsafe_unretained id const obj, - __unsafe_unretained RLMProperty *const prop) { - switch (prop.type) { - case RLMPropertyTypeString: - case RLMPropertyTypeBool: - case RLMPropertyTypeDate: - case RLMPropertyTypeInt: - case RLMPropertyTypeFloat: - case RLMPropertyTypeDouble: - case RLMPropertyTypeData: - if (!RLMIsObjectValidForProperty(obj, prop)) { - @throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name); - } - break; - case RLMPropertyTypeObject: - break; - case RLMPropertyTypeArray: { - if (obj != nil && obj != NSNull.null) { - if (![obj conformsToProtocol:@protocol(NSFastEnumeration)]) { - @throw RLMException(@"Array property value (%@) is not enumerable.", obj); - } - } - break; - } - case RLMPropertyTypeAny: - case RLMPropertyTypeLinkingObjects: - @throw RLMException(@"Invalid value '%@' for property '%@'", obj, prop.name); - } -} - -static NSUInteger createRowForObject(RLMClassInfo const& info) { - try { - return info.table()->add_empty_row(); - } - catch (std::exception const& e) { - @throw RLMException(e); - } -} - -/* If a row exists with the specified primary key value, return its index. Otherwise, return `realm::not_found`. - * - * Precondition: `info` must refer to a class which has a primary key property - * Precondition: `primaryValue` is a validated property value that has been coerced to `nil` - */ -static NSUInteger getRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue) { - REALM_ASSERT_DEBUG(info.propertyForPrimaryKey()); - - RLMProperty *const primaryProperty = info.propertyForPrimaryKey(); - const NSUInteger primaryPropertyColumn = info.tableColumn(primaryProperty); - - switch (primaryProperty.type) { - case RLMPropertyTypeString: - return info.table()->find_first_string(primaryPropertyColumn, RLMStringDataWithNSString(primaryValue)); - - case RLMPropertyTypeInt: - if (primaryValue) { - return info.table()->find_first_int(primaryPropertyColumn, [primaryValue longLongValue]); - } else { - return info.table()->find_first_null(primaryPropertyColumn); - } - - default: - REALM_UNREACHABLE(); - } -} - -/* Create a row with the specified primary key value and return its index. - * - * Precondition: `info` must refer to a class which has a valid primary key property - * Precondition: a write transaction is in progress - * Precondition: no row already exists with the specified `primaryValue` for this model - */ -static NSUInteger createRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue) { - REALM_ASSERT_DEBUG(info.propertyForPrimaryKey()); - REALM_ASSERT_DEBUG(info.realm.inWriteTransaction); - REALM_ASSERT_DEBUG(getRowForObjectWithPrimaryKey(info, primaryValue) == realm::not_found); - - RLMProperty *const primaryProperty = info.propertyForPrimaryKey(); - const NSUInteger primaryColumnIndex = info.tableColumn(primaryProperty); - - // create row - const NSUInteger rowIndex = createRowForObject(info); - Row row = info.table()->get(rowIndex); - - // set value for primary key - validateValueForProperty(primaryValue, primaryProperty); - primaryValue = RLMCoerceToNil(primaryValue); - - try { - switch (primaryProperty.type) { - case RLMPropertyTypeString: - REALM_ASSERT_DEBUG(!primaryValue || [primaryValue isKindOfClass:NSString.class]); - row.set_string_unique(primaryColumnIndex, RLMStringDataWithNSString(primaryValue)); - break; - - case RLMPropertyTypeInt: - if (primaryValue) { - REALM_ASSERT_DEBUG([primaryValue isKindOfClass:NSNumber.class]); - row.set_int_unique(primaryColumnIndex, [primaryValue longLongValue]); - } else { - row.set_null(primaryColumnIndex); // FIXME: Use `set_null_unique` once Core supports it - } - break; - - default: - REALM_UNREACHABLE(); - } - } - catch (std::exception const& e) { - @throw RLMException(e); - } - return rowIndex; -} - -/* If a row exists with the specified primary key value, returns its index. Otherwise, creates a new row with the - * specified primary key value and returns its index. The out parameter `foundExisting` will be set to indicate - * whether or not a new row was created. - * - * Precondition: `info` must refer to a class which has a valid primary key property - * Precondition: a write transaction is in progress - */ -static NSUInteger createOrGetRowForObjectWithPrimaryKey(RLMClassInfo const& info, id primaryValue, - bool* foundExisting = nullptr) { - REALM_ASSERT_DEBUG(info.propertyForPrimaryKey()); - REALM_ASSERT_DEBUG(info.realm.inWriteTransaction); - - const NSUInteger existingRow = getRowForObjectWithPrimaryKey(info, primaryValue); - if (existingRow == realm::not_found) { - *foundExisting = false; - return createRowForObjectWithPrimaryKey(info, primaryValue); - } else { - *foundExisting = true; - return existingRow; - } -} - -/* If the class has a primary key, calls `valueForProperty` with that key and creates or gets the row with - * this primary key value. Otherwise if the class has no primary key, creates a new row. The out parameter - * `foundExisting` will be set to indicate whether or not a new row was created. - * - * Precondition: a write transaction is in progress - */ -template -static NSUInteger createOrGetRowForObject(RLMClassInfo const& info, F valueForProperty, - bool createOrUpdate, bool* foundExisting) { - // try to get existing row if this class has a primary key - if (RLMProperty *primaryProperty = info.propertyForPrimaryKey()) { - // get primary value - const id primaryValue = valueForProperty(primaryProperty); - - // search for existing object based on primary key type, creating a new row if one does not exist - NSUInteger rowIndex = createOrGetRowForObjectWithPrimaryKey(info, RLMCoerceToNil(primaryValue), foundExisting); - - // ensure that `createOrUpdate` is set if we found an existing row - if (*foundExisting && !createOrUpdate) { - @throw RLMException(@"Can't create object with existing primary key value '%@'.", primaryValue); - } - return rowIndex; - } - // if no existing, create row - else { - *foundExisting = false; - return createRowForObject(info); - } -} - -void RLMAddObjectToRealm(__unsafe_unretained RLMObjectBase *const object, - __unsafe_unretained RLMRealm *const realm, - bool createOrUpdate) { - RLMVerifyInWriteTransaction(realm); - - // verify that object is unmanaged - if (object.invalidated) { - @throw RLMException(@"Adding a deleted or invalidated object to a Realm is not permitted"); - } - if (object->_realm) { - if (object->_realm == realm) { - // no-op - return; - } - // for differing realms users must explicitly create the object in the second realm - @throw RLMException(@"Object is already managed by another Realm"); - } - if (object->_observationInfo && object->_observationInfo->hasObservers()) { - @throw RLMException(@"Cannot add an object with observers to a Realm"); - } - - // set the realm and schema - NSString *objectClassName = object->_objectSchema.className; - auto& info = realm->_info[objectClassName]; - object->_info = &info; - object->_objectSchema = info.rlmObjectSchema; - object->_realm = realm; - - // get or create row - bool foundExisting; - auto primaryGetter = [=](__unsafe_unretained RLMProperty *const p) { return [object valueForKey:p.name]; }; - object->_row = (*info.table())[createOrGetRowForObject(info, primaryGetter, createOrUpdate, &foundExisting)]; - - RLMCreationOptions creationOptions = RLMCreationOptionsPromoteUnmanaged; - if (createOrUpdate) { - creationOptions |= RLMCreationOptionsCreateOrUpdate; - } - - // populate all properties - for (RLMProperty *prop in info.rlmObjectSchema.properties) { - // skip primary key when updating since it doesn't change - if (prop.isPrimary) - continue; - - // get object from ivar using key value coding - id value = nil; - if (prop.swiftIvar) { - if (prop.type == RLMPropertyTypeArray) { - value = static_cast(object_getIvar(object, prop.swiftIvar))._rlmArray; - } - else { // optional - value = static_cast(object_getIvar(object, prop.swiftIvar)).underlyingValue; - } - } - else if ([object respondsToSelector:prop.getterSel]) { - value = [object valueForKey:prop.getterName]; - } - - if (!value && !prop.optional) { - @throw RLMException(@"No value or default value specified for property '%@' in '%@'", - prop.name, info.rlmObjectSchema.className); - } - - // set the ivars for object and array properties to nil as otherwise the - // accessors retain objects that are no longer accessible via the properties - // this is mainly an issue when the object graph being added has cycles, - // as it's not obvious that the user has to set the *ivars* to nil to - // avoid leaking memory - if (prop.type == RLMPropertyTypeObject || prop.type == RLMPropertyTypeArray) { - if (!prop.swiftIvar) { - ((void(*)(id, SEL, id))objc_msgSend)(object, prop.setterSel, nil); - } - } - - // set in table with out validation - RLMDynamicSet(object, prop, RLMCoerceToNil(value), creationOptions); - } - - // set to proper accessor class - object_setClass(object, info.rlmObjectSchema.accessorClass); - - RLMInitializeSwiftAccessorGenerics(object); -} - -RLMObjectBase *RLMCreateObjectInRealmWithValue(RLMRealm *realm, NSString *className, id value, bool createOrUpdate = false) { - if (createOrUpdate && RLMIsObjectSubclass([value class])) { - RLMObjectBase *obj = value; - if ([obj->_objectSchema.className isEqualToString:className] && obj->_realm == realm) { - // This is a no-op if value is an RLMObject of the same type already backed by the target realm. - return value; - } - } - - // verify writable - RLMVerifyInWriteTransaction(realm); - - // create the object - auto& info = realm->_info[className]; - RLMObjectBase *object = RLMCreateManagedAccessor(info.rlmObjectSchema.accessorClass, realm, &info); - - RLMCreationOptions creationOptions = createOrUpdate ? RLMCreationOptionsCreateOrUpdate : RLMCreationOptionsNone; - - // create row, and populate - if (NSArray *array = RLMDynamicCast(value)) { - // get or create our accessor - bool foundExisting; - NSArray *props = info.rlmObjectSchema.properties; - auto primaryGetter = [=](__unsafe_unretained RLMProperty *const p) { - return array[[props indexOfObject:p]]; - }; - object->_row = (*info.table())[createOrGetRowForObject(info, primaryGetter, createOrUpdate, &foundExisting)]; - - // populate - for (NSUInteger i = 0; i < array.count; i++) { - RLMProperty *prop = props[i]; - - // skip primary key when updating since it doesn't change - if (prop.isPrimary) - continue; - - id val = array[i]; - validateValueForProperty(val, prop); - RLMDynamicSet(object, prop, RLMCoerceToNil(val), creationOptions); - } - } - else { - __block bool foundExisting = false; - __block NSDictionary *defaultValues = nil; - __block bool usedDefault = false; - auto getValue = ^(RLMProperty *prop) { - id propValue = RLMValidatedValueForProperty(value, prop.name, info.rlmObjectSchema.className); - usedDefault = !propValue && !foundExisting; - if (usedDefault) { - if (!defaultValues) { - defaultValues = RLMDefaultValuesForObjectSchema(info.rlmObjectSchema); - } - propValue = defaultValues[prop.name]; - if (!propValue && (prop.type == RLMPropertyTypeObject || prop.type == RLMPropertyTypeArray)) { - propValue = NSNull.null; - } - } - return propValue; - }; - // get or create our accessor - object->_row = (*info.table())[createOrGetRowForObject(info, getValue, createOrUpdate, &foundExisting)]; - - // populate - for (RLMProperty *prop in info.rlmObjectSchema.properties) { - // skip primary key when updating since it doesn't change - if (prop.isPrimary) - continue; - - if (id propValue = getValue(prop)) { - validateValueForProperty(propValue, prop); - // add SetDefault to creationoptions - RLMCreationOptions propertyCreationOptions = creationOptions; - if (usedDefault) { - propertyCreationOptions |= RLMCreationOptionsSetDefault; - } - RLMDynamicSet(object, prop, RLMCoerceToNil(propValue), propertyCreationOptions); - } - else if (!foundExisting && !prop.optional) { - @throw RLMException(@"Property '%@' of object of type '%@' cannot be nil.", prop.name, info.rlmObjectSchema.className); - } - } - } - - RLMInitializeSwiftAccessorGenerics(object); - return object; -} - -void RLMDeleteObjectFromRealm(__unsafe_unretained RLMObjectBase *const object, - __unsafe_unretained RLMRealm *const realm) { - if (realm != object->_realm) { - @throw RLMException(@"Can only delete an object from the Realm it belongs to."); - } - - RLMVerifyInWriteTransaction(object->_realm); - - // move last row to row we are deleting - if (object->_row.is_attached()) { - RLMTrackDeletions(realm, ^{ - object->_row.get_table()->move_last_over(object->_row.get_index()); - }); - } - - // set realm to nil - object->_realm = nil; -} - -void RLMDeleteAllObjectsFromRealm(RLMRealm *realm) { - RLMVerifyInWriteTransaction(realm); - - // clear table for each object schema - for (auto& info : realm->_info) { - RLMClearTable(info.second); - } -} - -RLMResults *RLMGetObjects(RLMRealm *realm, NSString *objectClassName, NSPredicate *predicate) { - RLMVerifyRealmRead(realm); - - // create view from table and predicate - RLMClassInfo& info = realm->_info[objectClassName]; - if (!info.table()) { - // read-only realms may be missing tables since we can't add any - // missing ones on init - return [RLMResults resultsWithObjectInfo:info results:{}]; - } - - if (predicate) { - realm::Query query = RLMPredicateToQuery(predicate, info.rlmObjectSchema, realm.schema, realm.group); - return [RLMResults resultsWithObjectInfo:info - results:realm::Results(realm->_realm, std::move(query))]; - } - - return [RLMResults resultsWithObjectInfo:info - results:realm::Results(realm->_realm, *info.table())]; -} - -id RLMGetObject(RLMRealm *realm, NSString *objectClassName, id key) { - RLMVerifyRealmRead(realm); - - RLMClassInfo& info = realm->_info[objectClassName]; - auto primaryProperty = info.objectSchema->primary_key_property(); - if (!primaryProperty) { - @throw RLMException(@"%@ does not have a primary key", objectClassName); - } - - auto table = info.table(); - if (!table) { - // read-only realms may be missing tables since we can't add any - // missing ones on init - return nil; - } - - key = RLMCoerceToNil(key); - if (!key && !primaryProperty->is_nullable) { - @throw RLMException(@"Invalid null value for non-nullable primary key."); - } - - size_t row = realm::not_found; - switch (primaryProperty->type) { - case PropertyType::String: { - NSString *string = RLMDynamicCast(key); - if (!key || string) { - row = table->find_first_string(primaryProperty->table_column, RLMStringDataWithNSString(string)); - } else { - @throw RLMException(@"Invalid value '%@' of type '%@' for string primary key.", key, [key class]); - } - break; - } - case PropertyType::Int: - if (NSNumber *number = RLMDynamicCast(key)) { - row = table->find_first_int(primaryProperty->table_column, number.longLongValue); - } else if (!key) { - row = table->find_first_null(primaryProperty->table_column); - } else { - @throw RLMException(@"Invalid value '%@' of type '%@' for int primary key.", key, [key class]); - } - break; - default: - REALM_UNREACHABLE(); - } - - if (row == realm::not_found) { - return nil; - } - - return RLMCreateObjectAccessor(realm, info, row); -} - -RLMObjectBase *RLMCreateObjectAccessor(__unsafe_unretained RLMRealm *const realm, - RLMClassInfo& info, - NSUInteger index) { - return RLMCreateObjectAccessor(realm, info, (*info.table())[index]); -} - -// Create accessor and register with realm -RLMObjectBase *RLMCreateObjectAccessor(__unsafe_unretained RLMRealm *const realm, - RLMClassInfo& info, - realm::RowExpr row) { - RLMObjectBase *accessor = RLMCreateManagedAccessor(info.rlmObjectSchema.accessorClass, realm, &info); - accessor->_row = row; - RLMInitializeSwiftAccessorGenerics(accessor); - return accessor; -} diff --git a/Example/Pods/Realm/Realm/RLMObservation.mm b/Example/Pods/Realm/Realm/RLMObservation.mm deleted file mode 100644 index e6538b6..0000000 --- a/Example/Pods/Realm/Realm/RLMObservation.mm +++ /dev/null @@ -1,500 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 "RLMObservation.hpp" - -#import "RLMAccessor.h" -#import "RLMArray_Private.hpp" -#import "RLMListBase.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObject_Private.hpp" -#import "RLMProperty_Private.h" -#import "RLMRealm_Private.hpp" - -#import - -using namespace realm; - -namespace { - template - struct IteratorPair { - Iterator first; - Iterator second; - }; - template - Iterator begin(IteratorPair const& p) { - return p.first; - } - template - Iterator end(IteratorPair const& p) { - return p.second; - } - - template - auto reverse(Container const& c) { - return IteratorPair{c.rbegin(), c.rend()}; - } -} - -RLMObservationInfo::RLMObservationInfo(RLMClassInfo &objectSchema, std::size_t row, id object) -: object(object) -, objectSchema(&objectSchema) -{ - setRow(*objectSchema.table(), row); -} - -RLMObservationInfo::RLMObservationInfo(id object) -: object(object) -{ -} - -RLMObservationInfo::~RLMObservationInfo() { - if (prev) { - // Not the head of the linked list, so just detach from the list - REALM_ASSERT_DEBUG(prev->next == this); - prev->next = next; - if (next) { - REALM_ASSERT_DEBUG(next->prev == this); - next->prev = prev; - } - } - else if (objectSchema) { - // The head of the list, so remove self from the object schema's array - // of observation info, either replacing self with the next info or - // removing entirely if there is no next - auto end = objectSchema->observedObjects.end(); - auto it = find(objectSchema->observedObjects.begin(), end, this); - if (it != end) { - if (next) { - *it = next; - next->prev = nullptr; - } - else { - iter_swap(it, std::prev(end)); - objectSchema->observedObjects.pop_back(); - } - } - } - // Otherwise the observed object was unmanaged, so nothing to do - -#ifdef DEBUG - // ensure that incorrect cleanup fails noisily - object = (__bridge id)(void *)-1; - prev = (RLMObservationInfo *)-1; - next = (RLMObservationInfo *)-1; -#endif -} - -NSString *RLMObservationInfo::columnName(size_t col) const noexcept { - return objectSchema->propertyForTableColumn(col).name; -} - -void RLMObservationInfo::willChange(NSString *key, NSKeyValueChange kind, NSIndexSet *indexes) const { - if (indexes) { - forEach([=](__unsafe_unretained auto o) { - [o willChange:kind valuesAtIndexes:indexes forKey:key]; - }); - } - else { - forEach([=](__unsafe_unretained auto o) { - [o willChangeValueForKey:key]; - }); - } -} - -void RLMObservationInfo::didChange(NSString *key, NSKeyValueChange kind, NSIndexSet *indexes) const { - if (indexes) { - forEach([=](__unsafe_unretained auto o) { - [o didChange:kind valuesAtIndexes:indexes forKey:key]; - }); - } - else { - forEach([=](__unsafe_unretained auto o) { - [o didChangeValueForKey:key]; - }); - } -} - -void RLMObservationInfo::prepareForInvalidation() { - REALM_ASSERT_DEBUG(objectSchema); - REALM_ASSERT_DEBUG(!prev); - for (auto info = this; info; info = info->next) - info->invalidated = true; -} - -void RLMObservationInfo::setRow(realm::Table &table, size_t newRow) { - REALM_ASSERT_DEBUG(!row); - REALM_ASSERT_DEBUG(objectSchema); - row = table[newRow]; - for (auto info : objectSchema->observedObjects) { - if (info->row && info->row.get_index() == row.get_index()) { - prev = info; - next = info->next; - if (next) - next->prev = this; - info->next = this; - return; - } - } - objectSchema->observedObjects.push_back(this); -} - -void RLMObservationInfo::recordObserver(realm::Row& objectRow, RLMClassInfo *objectInfo, - __unsafe_unretained RLMObjectSchema *const objectSchema, - __unsafe_unretained NSString *const keyPath) { - ++observerCount; - if (row) { - return; - } - - // add ourselves to the list of observed objects if this is the first time - // an observer is being added to a managed object - if (objectRow) { - this->objectSchema = objectInfo; - setRow(*objectRow.get_table(), objectRow.get_index()); - return; - } - - // Arrays need a reference to their containing object to avoid having to - // go through the awful proxy object from mutableArrayValueForKey. - // For managed objects we do this when the object is added or created - // (and have to to support notifications from modifying an object which - // was never observed), but for Swift classes (both RealmSwift and - // RLMObject) we can't do it then because we don't know what the parent - // object is. - - NSUInteger sep = [keyPath rangeOfString:@"."].location; - NSString *key = sep == NSNotFound ? keyPath : [keyPath substringToIndex:sep]; - RLMProperty *prop = objectSchema[key]; - if (prop && prop.type == RLMPropertyTypeArray) { - id value = valueForKey(key); - RLMArray *array = [value isKindOfClass:[RLMListBase class]] ? [value _rlmArray] : value; - array->_key = key; - array->_parentObject = object; - } - else if (auto swiftIvar = prop.swiftIvar) { - if (auto optional = RLMDynamicCast(object_getIvar(object, swiftIvar))) { - optional.property = prop; - optional.object = object; - } - } -} - -void RLMObservationInfo::removeObserver() { - --observerCount; -} - -id RLMObservationInfo::valueForKey(NSString *key) { - if (invalidated) { - if ([key isEqualToString:RLMInvalidatedKey]) { - return @YES; - } - return cachedObjects[key]; - } - - if (key != lastKey) { - lastKey = key; - lastProp = objectSchema ? objectSchema->rlmObjectSchema[key] : nil; - } - - static auto superValueForKey = reinterpret_cast([NSObject methodForSelector:@selector(valueForKey:)]); - if (!lastProp) { - // Not a managed property, so use NSObject's implementation of valueForKey: - return RLMCoerceToNil(superValueForKey(object, @selector(valueForKey:), key)); - } - - auto getSuper = [&] { - return row ? RLMDynamicGet(object, lastProp) : RLMCoerceToNil(superValueForKey(object, @selector(valueForKey:), key)); - }; - - // We need to return the same object each time for observing over keypaths - // to work, so we store a cache of them here. We can't just cache them on - // the object as that leads to retain cycles. - if (lastProp.type == RLMPropertyTypeArray) { - RLMArray *value = cachedObjects[key]; - if (!value) { - value = getSuper(); - if (!cachedObjects) { - cachedObjects = [NSMutableDictionary new]; - } - cachedObjects[key] = value; - } - return value; - } - - if (lastProp.type == RLMPropertyTypeObject) { - size_t col = row.get_column_index(lastProp.name.UTF8String); - if (row.is_null_link(col)) { - [cachedObjects removeObjectForKey:key]; - return nil; - } - - RLMObjectBase *value = cachedObjects[key]; - if (value && value->_row.get_index() == row.get_link(col)) { - return value; - } - value = getSuper(); - if (!cachedObjects) { - cachedObjects = [NSMutableDictionary new]; - } - cachedObjects[key] = value; - return value; - } - - return getSuper(); -} - -RLMObservationInfo *RLMGetObservationInfo(RLMObservationInfo *info, size_t row, - RLMClassInfo& objectSchema) { - if (info) { - return info; - } - - for (RLMObservationInfo *info : objectSchema.observedObjects) { - if (info->isForRow(row)) { - return info; - } - } - - return nullptr; -} - -void RLMClearTable(RLMClassInfo &objectSchema) { - for (auto info : objectSchema.observedObjects) { - info->willChange(RLMInvalidatedKey); - } - - RLMTrackDeletions(objectSchema.realm, ^{ - objectSchema.table()->clear(); - - for (auto info : objectSchema.observedObjects) { - info->prepareForInvalidation(); - } - }); - - for (auto info : reverse(objectSchema.observedObjects)) { - info->didChange(RLMInvalidatedKey); - } - - objectSchema.observedObjects.clear(); -} - -void RLMTrackDeletions(__unsafe_unretained RLMRealm *const realm, dispatch_block_t block) { - std::vector *> observers; - - // Build up an array of observation info arrays which is indexed by table - // index (the object schemata may be in an entirely different order) - for (auto& info : realm->_info) { - if (info.second.observedObjects.empty()) { - continue; - } - size_t ndx = info.second.table()->get_index_in_group(); - if (ndx >= observers.size()) { - observers.resize(std::max(observers.size() * 2, ndx + 1)); - } - observers[ndx] = &info.second.observedObjects; - } - - // No need for change tracking if no objects are observed - if (observers.empty()) { - block(); - return; - } - - struct change { - RLMObservationInfo *info; - __unsafe_unretained NSString *property; - NSMutableIndexSet *indexes; - }; - - std::vector changes; - std::vector invalidated; - - // This callback is called by core with a list of row deletions and - // resulting link nullifications immediately before things are deleted and nullified - realm.group.set_cascade_notification_handler([&](realm::Group::CascadeNotification const& cs) { - for (auto const& link : cs.links) { - size_t table_ndx = link.origin_table->get_index_in_group(); - if (table_ndx >= observers.size() || !observers[table_ndx]) { - // The modified table has no observers - continue; - } - - for (auto observer : *observers[table_ndx]) { - if (!observer->isForRow(link.origin_row_ndx)) { - continue; - } - - NSString *name = observer->columnName(link.origin_col_ndx); - if (observer->getRow().get_table()->get_column_type(link.origin_col_ndx) != type_LinkList) { - changes.push_back({observer, name}); - continue; - } - - auto c = find_if(begin(changes), end(changes), [&](auto const& c) { - return c.info == observer && c.property == name; - }); - if (c == end(changes)) { - changes.push_back({observer, name, [NSMutableIndexSet new]}); - c = prev(end(changes)); - } - - // We know what row index is being removed from the LinkView, - // but what we actually want is the indexes in the LinkView that - // are going away - auto linkview = observer->getRow().get_linklist(link.origin_col_ndx); - size_t start = 0, index; - while ((index = linkview->find(link.old_target_row_ndx, start)) != realm::not_found) { - [c->indexes addIndex:index]; - start = index + 1; - } - } - } - - for (auto const& row : cs.rows) { - if (row.table_ndx >= observers.size() || !observers[row.table_ndx]) { - // The modified table has no observers - continue; - } - - for (auto observer : *observers[row.table_ndx]) { - if (observer->isForRow(row.row_ndx)) { - invalidated.push_back(observer); - break; - } - } - } - - // The relative order of these loops is very important - for (auto info : invalidated) { - info->willChange(RLMInvalidatedKey); - } - for (auto const& change : changes) { - change.info->willChange(change.property, NSKeyValueChangeRemoval, change.indexes); - } - for (auto info : invalidated) { - info->prepareForInvalidation(); - } - }); - - try { - block(); - } - catch (...) { - realm.group.set_cascade_notification_handler(nullptr); - throw; - } - - for (auto const& change : reverse(changes)) { - change.info->didChange(change.property, NSKeyValueChangeRemoval, change.indexes); - } - for (auto info : reverse(invalidated)) { - info->didChange(RLMInvalidatedKey); - } - - realm.group.set_cascade_notification_handler(nullptr); -} - -namespace { -template -void forEach(realm::BindingContext::ObserverState const& state, Func&& func) { - for (size_t i = 0, size = state.changes.size(); i < size; ++i) { - if (state.changes[i].kind != realm::BindingContext::ColumnInfo::Kind::None) { - func(i, state.changes[i], static_cast(state.info)); - } - } -} -} - -std::vector RLMGetObservedRows(RLMSchemaInfo const& schema) { - std::vector observers; - for (auto& table : schema) { - for (auto info : table.second.observedObjects) { - auto const& row = info->getRow(); - if (!row.is_attached()) - continue; - observers.push_back({ - row.get_table()->get_index_in_group(), - row.get_index(), - info}); - } - } - sort(begin(observers), end(observers)); - return observers; -} - -static NSKeyValueChange convert(realm::BindingContext::ColumnInfo::Kind kind) { - switch (kind) { - case realm::BindingContext::ColumnInfo::Kind::None: - case realm::BindingContext::ColumnInfo::Kind::SetAll: - return NSKeyValueChangeSetting; - case realm::BindingContext::ColumnInfo::Kind::Set: - return NSKeyValueChangeReplacement; - case realm::BindingContext::ColumnInfo::Kind::Insert: - return NSKeyValueChangeInsertion; - case realm::BindingContext::ColumnInfo::Kind::Remove: - return NSKeyValueChangeRemoval; - } -} - -static NSIndexSet *convert(realm::IndexSet const& in, NSMutableIndexSet *out) { - if (in.empty()) { - return nil; - } - - [out removeAllIndexes]; - for (auto range : in) { - [out addIndexesInRange:{range.first, range.second - range.first}]; - } - return out; -} - -void RLMWillChange(std::vector const& observed, - std::vector const& invalidated) { - for (auto info : invalidated) { - static_cast(info)->willChange(RLMInvalidatedKey); - } - if (!observed.empty()) { - NSMutableIndexSet *indexes = [NSMutableIndexSet new]; - for (auto const& o : observed) { - forEach(o, [&](size_t, auto const& change, RLMObservationInfo *info) { - info->willChange(info->columnName(change.initial_column_index), - convert(change.kind), convert(change.indices, indexes)); - }); - } - } - for (auto info : invalidated) { - static_cast(info)->prepareForInvalidation(); - } -} - -void RLMDidChange(std::vector const& observed, - std::vector const& invalidated) { - if (!observed.empty()) { - // Loop in reverse order to avoid O(N^2) behavior in Foundation - NSMutableIndexSet *indexes = [NSMutableIndexSet new]; - for (auto const& o : reverse(observed)) { - forEach(o, [&](size_t i, auto const& change, RLMObservationInfo *info) { - info->didChange(info->columnName(i), convert(change.kind), convert(change.indices, indexes)); - }); - } - } - for (auto const& info : reverse(invalidated)) { - static_cast(info)->didChange(RLMInvalidatedKey); - } -} diff --git a/Example/Pods/Realm/Realm/RLMOptionalBase.mm b/Example/Pods/Realm/Realm/RLMOptionalBase.mm deleted file mode 100644 index 8aad1c8..0000000 --- a/Example/Pods/Realm/Realm/RLMOptionalBase.mm +++ /dev/null @@ -1,89 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 "RLMAccessor.h" -#import "RLMOptionalBase.h" -#import "RLMObject_Private.h" -#import "RLMObjectStore.h" -#import "RLMProperty_Private.h" -#import "RLMUtil.hpp" - -#import - -@interface RLMOptionalBase () -@property (nonatomic) id unmanagedValue; -@end - -@implementation RLMOptionalBase - -- (instancetype)init { - return self; -} - -- (id)underlyingValue { - if ((_object && _object->_realm) || _object.isInvalidated) { - return RLMDynamicGet(_object, _property); - } - else { - return _unmanagedValue; - } -} - -- (void)setUnderlyingValue:(id)underlyingValue { - if ((_object && _object->_realm) || _object.isInvalidated) { - if (_property.isPrimary) { - @throw RLMException(@"Primary key can't be changed after an object is inserted."); - } - RLMDynamicSet(_object, _property, underlyingValue, RLMCreationOptionsNone); - } - else { - NSString *propertyName = _property.name; - [_object willChangeValueForKey:propertyName]; - _unmanagedValue = underlyingValue; - [_object didChangeValueForKey:propertyName]; - } -} - -- (BOOL)isKindOfClass:(Class)aClass { - return [self.underlyingValue isKindOfClass:aClass] || RLMIsKindOfClass(object_getClass(self), aClass); -} - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { - return [self.underlyingValue methodSignatureForSelector:sel]; -} - -- (void)forwardInvocation:(NSInvocation *)invocation { - [invocation invokeWithTarget:self.underlyingValue]; -} - -- (id)forwardingTargetForSelector:(__unused SEL)sel { - return self.underlyingValue; -} - -- (BOOL)respondsToSelector:(SEL)aSelector { - if (id val = self.underlyingValue) { - return [val respondsToSelector:aSelector]; - } - return NO; -} - -- (void)doesNotRecognizeSelector:(SEL)aSelector { - [self.underlyingValue doesNotRecognizeSelector:aSelector]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMPredicateUtil.mm b/Example/Pods/Realm/Realm/RLMPredicateUtil.mm deleted file mode 100644 index d2f722b..0000000 --- a/Example/Pods/Realm/Realm/RLMPredicateUtil.mm +++ /dev/null @@ -1,118 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 "RLMPredicateUtil.hpp" - -// NSConditionalExpressionType is new in OS X 10.11 and iOS 9.0 -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#define CONDITIONAL_EXPRESSION_DECLARED (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define CONDITIONAL_EXPRESSION_DECLARED (__IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) -#else -#define CONDITIONAL_EXPRESSION_DECLARED 0 -#endif - -#if !CONDITIONAL_EXPRESSION_DECLARED - -#define NSConditionalExpressionType 20 - -@interface NSExpression (NewIn1011And90) -+ (NSExpression *)expressionForConditional:(NSPredicate *)predicate trueExpression:(NSExpression *)trueExpression falseExpression:(NSExpression *)falseExpression; -- (NSExpression *)trueExpression; -- (NSExpression *)falseExpression; -@end - -#endif - -namespace { - -struct PredicateExpressionTransformer { - PredicateExpressionTransformer(ExpressionVisitor visitor) : m_visitor(visitor) { } - - NSExpression *visit(NSExpression *expression) const; - NSPredicate *visit(NSPredicate *predicate) const; - - ExpressionVisitor m_visitor; -}; - -NSExpression *PredicateExpressionTransformer::visit(NSExpression *expression) const { - expression = m_visitor(expression); - - switch (expression.expressionType) { - case NSFunctionExpressionType: { - NSMutableArray *arguments = [NSMutableArray array]; - for (NSExpression *argument in expression.arguments) { - [arguments addObject:visit(argument)]; - } - if (expression.operand) { - return [NSExpression expressionForFunction:visit(expression.operand) selectorName:expression.function arguments:arguments]; - } else { - return [NSExpression expressionForFunction:expression.function arguments:arguments]; - } - } - - case NSUnionSetExpressionType: - return [NSExpression expressionForUnionSet:visit(expression.leftExpression) with:visit(expression.rightExpression)]; - case NSIntersectSetExpressionType: - return [NSExpression expressionForIntersectSet:visit(expression.leftExpression) with:visit(expression.rightExpression)]; - case NSMinusSetExpressionType: - return [NSExpression expressionForMinusSet:visit(expression.leftExpression) with:visit(expression.rightExpression)]; - - case NSSubqueryExpressionType: - return [NSExpression expressionForSubquery:visit(expression.operand) usingIteratorVariable:expression.variable predicate:visit(expression.predicate)]; - - case NSAggregateExpressionType: { - NSMutableArray *subexpressions = [NSMutableArray array]; - for (NSExpression *subexpression in expression.collection) { - [subexpressions addObject:visit(subexpression)]; - } - return [NSExpression expressionForAggregate:subexpressions]; - } - - case NSConditionalExpressionType: - return [NSExpression expressionForConditional:visit(expression.predicate) trueExpression:visit(expression.trueExpression) falseExpression:visit(expression.falseExpression)]; - - default: - // The remaining expression types do not contain nested expressions or predicates. - return expression; - } -} - -NSPredicate *PredicateExpressionTransformer::visit(NSPredicate *predicate) const { - if ([predicate isKindOfClass:[NSCompoundPredicate class]]) { - NSCompoundPredicate *compoundPredicate = (NSCompoundPredicate *)predicate; - NSMutableArray *subpredicates = [NSMutableArray array]; - for (NSPredicate *subpredicate in compoundPredicate.subpredicates) { - [subpredicates addObject:visit(subpredicate)]; - } - return [[NSCompoundPredicate alloc] initWithType:compoundPredicate.compoundPredicateType subpredicates:subpredicates]; - } - if ([predicate isKindOfClass:[NSComparisonPredicate class]]) { - NSComparisonPredicate *comparisonPredicate = (NSComparisonPredicate *)predicate; - NSExpression *leftExpression = visit(comparisonPredicate.leftExpression); - NSExpression *rightExpression = visit(comparisonPredicate.rightExpression); - return [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression:rightExpression modifier:comparisonPredicate.comparisonPredicateModifier type:comparisonPredicate.predicateOperatorType options:comparisonPredicate.options]; - } - return predicate; -} - -} // anonymous namespace - -NSPredicate *transformPredicate(NSPredicate *predicate, ExpressionVisitor visitor) { - PredicateExpressionTransformer transformer(visitor); - return transformer.visit(predicate); -} diff --git a/Example/Pods/Realm/Realm/RLMProperty.mm b/Example/Pods/Realm/Realm/RLMProperty.mm deleted file mode 100644 index 2ce75f4..0000000 --- a/Example/Pods/Realm/Realm/RLMProperty.mm +++ /dev/null @@ -1,569 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMProperty_Private.hpp" - -#import "RLMArray.h" -#import "RLMListBase.h" -#import "RLMObject.h" -#import "RLMObject_Private.h" -#import "RLMOptionalBase.h" -#import "RLMSchema_Private.h" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -BOOL RLMPropertyTypeIsNullable(RLMPropertyType propertyType) { - return propertyType != RLMPropertyTypeArray && propertyType != RLMPropertyTypeLinkingObjects; -} - -BOOL RLMPropertyTypeIsComputed(RLMPropertyType propertyType) { - return propertyType == RLMPropertyTypeLinkingObjects; -} - -static bool rawTypeIsComputedProperty(NSString *rawType) { - if ([rawType isEqualToString:@"@\"RLMLinkingObjects\""] || [rawType hasPrefix:@"@\"RLMLinkingObjects<"]) { - return true; - } - - return false; -} - -@implementation RLMProperty - -+ (instancetype)propertyForObjectStoreProperty:(const realm::Property &)prop { - return [[RLMProperty alloc] initWithName:@(prop.name.c_str()) - type:(RLMPropertyType)prop.type - objectClassName:prop.object_type.length() ? @(prop.object_type.c_str()) : nil - linkOriginPropertyName:prop.link_origin_property_name.length() ? @(prop.link_origin_property_name.c_str()) : nil - indexed:prop.is_indexed - optional:prop.is_nullable]; -} - -- (instancetype)initWithName:(NSString *)name - type:(RLMPropertyType)type - objectClassName:(NSString *)objectClassName - linkOriginPropertyName:(NSString *)linkOriginPropertyName - indexed:(BOOL)indexed - optional:(BOOL)optional { - self = [super init]; - if (self) { - _name = name; - _type = type; - _objectClassName = objectClassName; - _linkOriginPropertyName = linkOriginPropertyName; - _indexed = indexed; - _optional = optional; - [self setObjcCodeFromType]; - [self updateAccessors]; - } - - return self; -} - -- (void)setName:(NSString *)name { - _name = name; - [self updateAccessors]; -} - -- (void)updateAccessors { - // populate getter/setter names if generic - if (!_getterName) { - _getterName = _name; - } - if (!_setterName) { - // Objective-C setters only capitalize the first letter of the property name if it falls between 'a' and 'z' - int asciiCode = [_name characterAtIndex:0]; - BOOL shouldUppercase = asciiCode >= 'a' && asciiCode <= 'z'; - NSString *firstChar = [_name substringToIndex:1]; - firstChar = shouldUppercase ? firstChar.uppercaseString : firstChar; - _setterName = [NSString stringWithFormat:@"set%@%@:", firstChar, [_name substringFromIndex:1]]; - } - - _getterSel = NSSelectorFromString(_getterName); - _setterSel = NSSelectorFromString(_setterName); -} - --(void)setObjcCodeFromType { - if (_optional) { - _objcType = '@'; - return; - } - switch (_type) { - case RLMPropertyTypeInt: - _objcType = 'q'; - break; - case RLMPropertyTypeBool: - _objcType = 'c'; - break; - case RLMPropertyTypeDouble: - _objcType = 'd'; - break; - case RLMPropertyTypeFloat: - _objcType = 'f'; - break; - case RLMPropertyTypeAny: - case RLMPropertyTypeArray: - case RLMPropertyTypeData: - case RLMPropertyTypeDate: - case RLMPropertyTypeObject: - case RLMPropertyTypeString: - case RLMPropertyTypeLinkingObjects: - _objcType = '@'; - break; - } -} - -// determine RLMPropertyType from objc code - returns true if valid type was found/set -- (BOOL)setTypeFromRawType { - const char *code = _objcRawType.UTF8String; - _objcType = *code; // first char of type attr - - // map to RLMPropertyType - switch (self.objcType) { - case 's': // short - case 'i': // int - case 'l': // long - case 'q': // long long - _type = RLMPropertyTypeInt; - return YES; - case 'f': - _type = RLMPropertyTypeFloat; - return YES; - case 'd': - _type = RLMPropertyTypeDouble; - return YES; - case 'c': // BOOL is stored as char - since rlm has no char type this is ok - case 'B': - _type = RLMPropertyTypeBool; - return YES; - case '@': { - _optional = true; - static const char arrayPrefix[] = "@\"RLMArray<"; - static const int arrayPrefixLen = sizeof(arrayPrefix) - 1; - - static const char numberPrefix[] = "@\"NSNumber<"; - static const int numberPrefixLen = sizeof(numberPrefix) - 1; - - static const char linkingObjectsPrefix[] = "@\"RLMLinkingObjects"; - static const int linkingObjectsPrefixLen = sizeof(linkingObjectsPrefix) - 1; - - if (strcmp(code, "@\"NSString\"") == 0) { - _type = RLMPropertyTypeString; - } - else if (strcmp(code, "@\"NSDate\"") == 0) { - _type = RLMPropertyTypeDate; - } - else if (strcmp(code, "@\"NSData\"") == 0) { - _type = RLMPropertyTypeData; - } - else if (strncmp(code, arrayPrefix, arrayPrefixLen) == 0) { - _optional = false; - // get object class from type string - @"RLMArray" - _type = RLMPropertyTypeArray; - _objectClassName = [[NSString alloc] initWithBytes:code + arrayPrefixLen - length:strlen(code + arrayPrefixLen) - 2 // drop trailing >" - encoding:NSUTF8StringEncoding]; - - Class cls = [RLMSchema classForString:_objectClassName]; - if (!cls) { - @throw RLMException(@"Property '%@' is of type 'RLMArray<%@>' which is not a supported RLMArray object type. " - @"RLMArrays can only contain instances of RLMObject subclasses. " - @"See https://realm.io/docs/objc/latest/#to-many for more information.", _name, _objectClassName); - } - } - else if (strncmp(code, numberPrefix, numberPrefixLen) == 0) { - // get number type from type string - @"NSNumber" - NSString *numberType = [[NSString alloc] initWithBytes:code + numberPrefixLen - length:strlen(code + numberPrefixLen) - 2 // drop trailing >" - encoding:NSUTF8StringEncoding]; - - if ([numberType isEqualToString:@"RLMInt"]) { - _type = RLMPropertyTypeInt; - } - else if ([numberType isEqualToString:@"RLMFloat"]) { - _type = RLMPropertyTypeFloat; - } - else if ([numberType isEqualToString:@"RLMDouble"]) { - _type = RLMPropertyTypeDouble; - } - else if ([numberType isEqualToString:@"RLMBool"]) { - _type = RLMPropertyTypeBool; - } - else { - @throw RLMException(@"Property '%@' is of type 'NSNumber<%@>' which is not a supported NSNumber object type. " - @"NSNumbers can only be RLMInt, RLMFloat, RLMDouble, and RLMBool at the moment. " - @"See https://realm.io/docs/objc/latest for more information.", _name, numberType); - } - } - else if (strncmp(code, linkingObjectsPrefix, linkingObjectsPrefixLen) == 0 && - (code[linkingObjectsPrefixLen] == '"' || code[linkingObjectsPrefixLen] == '<')) { - _type = RLMPropertyTypeLinkingObjects; - _optional = false; - - if (!_objectClassName || !_linkOriginPropertyName) { - @throw RLMException(@"Property '%@' is of type RLMLinkingObjects but +linkingObjectsProperties did not specify the class " - "or property that is the origin of the link.", _name); - } - - // If the property was declared with a protocol indicating the contained type, validate that it matches - // the class from the dictionary returned by +linkingObjectsProperties. - if (code[linkingObjectsPrefixLen] == '<') { - NSString *classNameFromProtocol = [[NSString alloc] initWithBytes:code + linkingObjectsPrefixLen + 1 - length:strlen(code + linkingObjectsPrefixLen) - 3 // drop trailing >" - encoding:NSUTF8StringEncoding]; - if (![_objectClassName isEqualToString:classNameFromProtocol]) { - @throw RLMException(@"Property '%@' was declared with type RLMLinkingObjects<%@>, but a conflicting " - "class name of '%@' was returned by +linkingObjectsProperties.", _name, - classNameFromProtocol, _objectClassName); - } - } - } - else if (strcmp(code, "@\"NSNumber\"") == 0) { - @throw RLMException(@"Property '%@' requires a protocol defining the contained type - example: NSNumber.", _name); - } - else if (strcmp(code, "@\"RLMArray\"") == 0) { - @throw RLMException(@"Property '%@' requires a protocol defining the contained type - example: RLMArray.", _name); - } - else { - NSString *className; - Class cls = nil; - if (code[1] == '\0') { - className = @"id"; - } - else { - // for objects strip the quotes and @ - className = [_objcRawType substringWithRange:NSMakeRange(2, _objcRawType.length-3)]; - cls = [RLMSchema classForString:className]; - } - - if (!cls) { - @throw RLMException(@"Property '%@' is declared as '%@', which is not a supported RLMObject property type. " - @"All properties must be primitives, NSString, NSDate, NSData, NSNumber, RLMArray, RLMLinkingObjects, or subclasses of RLMObject. " - @"See https://realm.io/docs/objc/latest/api/Classes/RLMObject.html for more information.", _name, className); - } - - _type = RLMPropertyTypeObject; - _optional = true; - _objectClassName = [cls className] ?: className; - } - return YES; - } - default: - return NO; - } -} - -- (bool)parseObjcProperty:(objc_property_t)property { - unsigned int count; - objc_property_attribute_t *attrs = property_copyAttributeList(property, &count); - - bool isReadOnly = false; - for (size_t i = 0; i < count; ++i) { - switch (*attrs[i].name) { - case 'T': - _objcRawType = @(attrs[i].value); - break; - case 'R': - isReadOnly = true; - break; - case 'N': - // nonatomic - break; - case 'D': - // dynamic - break; - case 'G': - _getterName = @(attrs[i].value); - break; - case 'S': - _setterName = @(attrs[i].value); - break; - default: - break; - } - } - free(attrs); - - return isReadOnly; -} - -- (instancetype)initSwiftPropertyWithName:(NSString *)name - indexed:(BOOL)indexed - linkPropertyDescriptor:(RLMPropertyDescriptor *)linkPropertyDescriptor - property:(objc_property_t)property - instance:(RLMObject *)obj { - self = [super init]; - if (!self) { - return nil; - } - - _name = name; - _indexed = indexed; - - if (linkPropertyDescriptor) { - _objectClassName = [linkPropertyDescriptor.objectClass className]; - _linkOriginPropertyName = linkPropertyDescriptor.propertyName; - } - - if ([self parseObjcProperty:property]) { - return nil; - } - - id propertyValue = [obj valueForKey:_name]; - - // FIXME: temporarily workaround added since Objective-C generics used in Swift show up as `@` - // * broken starting in Swift 3.0 Xcode 8 b1 - // * tested to still be broken in Swift 3.0 Xcode 8 b6 - // * if the Realm Objective-C Swift tests pass with this removed, it's been fixed - // * once it has been fixed, remove this entire conditional block (contents included) entirely - // * Bug Report: SR-2031 https://bugs.swift.org/browse/SR-2031 - if ([_objcRawType isEqualToString:@"@"]) { - if (propertyValue) { - _objcRawType = [NSString stringWithFormat:@"@\"%@\"", [propertyValue class]]; - } else if (linkPropertyDescriptor) { - // we're going to naively assume that the user used the correct type since we can't check it - _objcRawType = @"@\"RLMLinkingObjects\""; - } - } - - // convert array types to objc variant - if ([_objcRawType isEqualToString:@"@\"RLMArray\""]) { - _objcRawType = [NSString stringWithFormat:@"@\"RLMArray<%@>\"", [propertyValue objectClassName]]; - } - else if ([_objcRawType isEqualToString:@"@\"NSNumber\""]) { - const char *numberType = [propertyValue objCType]; - if (!numberType) { - @throw RLMException(@"Can't persist NSNumber without default value: use a Swift-native number type or provide a default value."); - } - switch (*numberType) { - case 'i': - case 'l': - case 'q': - _objcRawType = @"@\"NSNumber\""; - break; - case 'f': - _objcRawType = @"@\"NSNumber\""; - break; - case 'd': - _objcRawType = @"@\"NSNumber\""; - break; - case 'B': - case 'c': - _objcRawType = @"@\"NSNumber\""; - break; - default: - @throw RLMException(@"Can't persist NSNumber of type '%s': only integers, floats, doubles, and bools are currently supported.", numberType); - } - } - - auto throwForPropertyName = ^(NSString *propertyName){ - @throw RLMException(@"Can't persist property '%@' with incompatible type. " - "Add to Object.ignoredProperties() class method to ignore.", - propertyName); - }; - - if (![self setTypeFromRawType]) { - throwForPropertyName(self.name); - } - - if (_objcType == 'c') { - // Check if it's a BOOL or Int8 by trying to set it to 2 and seeing if - // it actually sets it to 1. - [obj setValue:@2 forKey:name]; - NSNumber *value = [obj valueForKey:name]; - _type = value.intValue == 2 ? RLMPropertyTypeInt : RLMPropertyTypeBool; - } - - // update getter/setter names - [self updateAccessors]; - - return self; -} - -- (instancetype)initWithName:(NSString *)name - indexed:(BOOL)indexed - linkPropertyDescriptor:(RLMPropertyDescriptor *)linkPropertyDescriptor - property:(objc_property_t)property -{ - self = [super init]; - if (!self) { - return nil; - } - - _name = name; - _indexed = indexed; - - if (linkPropertyDescriptor) { - _objectClassName = [linkPropertyDescriptor.objectClass className]; - _linkOriginPropertyName = linkPropertyDescriptor.propertyName; - } - - bool isReadOnly = [self parseObjcProperty:property]; - bool isComputedProperty = rawTypeIsComputedProperty(_objcRawType); - if (isReadOnly && !isComputedProperty) { - return nil; - } - - if (![self setTypeFromRawType]) { - @throw RLMException(@"Can't persist property '%@' with incompatible type. " - "Add to ignoredPropertyNames: method to ignore.", self.name); - } - - if (!isReadOnly && isComputedProperty) { - @throw RLMException(@"Property '%@' must be declared as readonly as %@ properties cannot be written to.", - self.name, RLMTypeToString(_type)); - } - - // update getter/setter names - [self updateAccessors]; - - return self; -} - -- (instancetype)initSwiftListPropertyWithName:(NSString *)name - ivar:(Ivar)ivar - objectClassName:(NSString *)objectClassName { - self = [super init]; - if (!self) { - return nil; - } - - _name = name; - _type = RLMPropertyTypeArray; - _objectClassName = objectClassName; - _objcType = 't'; - _swiftIvar = ivar; - - // no obj-c property for generic lists, and thus no getter/setter names - - return self; -} - -- (instancetype)initSwiftOptionalPropertyWithName:(NSString *)name - indexed:(BOOL)indexed - ivar:(Ivar)ivar - propertyType:(RLMPropertyType)propertyType { - self = [super init]; - if (!self) { - return nil; - } - - _name = name; - _type = propertyType; - _indexed = indexed; - _objcType = '@'; - _swiftIvar = ivar; - _optional = true; - - // no obj-c property for generic optionals, and thus no getter/setter names - - return self; -} - -- (instancetype)initSwiftLinkingObjectsPropertyWithName:(NSString *)name - ivar:(Ivar)ivar - objectClassName:(NSString *)objectClassName - linkOriginPropertyName:(NSString *)linkOriginPropertyName { - self = [super init]; - if (!self) { - return nil; - } - - _name = name; - _type = RLMPropertyTypeLinkingObjects; - _objectClassName = objectClassName; - _linkOriginPropertyName = linkOriginPropertyName; - _objcType = '@'; - _swiftIvar = ivar; - - // no obj-c property for generic linking objects properties, and thus no getter/setter names - - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - RLMProperty *prop = [[RLMProperty allocWithZone:zone] init]; - prop->_name = _name; - prop->_type = _type; - prop->_objcType = _objcType; - prop->_objectClassName = _objectClassName; - prop->_indexed = _indexed; - prop->_getterName = _getterName; - prop->_setterName = _setterName; - prop->_getterSel = _getterSel; - prop->_setterSel = _setterSel; - prop->_isPrimary = _isPrimary; - prop->_swiftIvar = _swiftIvar; - prop->_optional = _optional; - prop->_linkOriginPropertyName = _linkOriginPropertyName; - - return prop; -} - -- (RLMProperty *)copyWithNewName:(NSString *)name { - RLMProperty *prop = [self copy]; - prop.name = name; - return prop; -} - -- (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[RLMProperty class]]) { - return NO; - } - - return [self isEqualToProperty:object]; -} - -- (BOOL)isEqualToProperty:(RLMProperty *)property { - return _type == property->_type - && _indexed == property->_indexed - && _isPrimary == property->_isPrimary - && _optional == property->_optional - && [_name isEqualToString:property->_name] - && (_objectClassName == property->_objectClassName || [_objectClassName isEqualToString:property->_objectClassName]) - && (_linkOriginPropertyName == property->_linkOriginPropertyName || [_linkOriginPropertyName isEqualToString:property->_linkOriginPropertyName]); -} - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ {\n\ttype = %@;\n\tobjectClassName = %@;\n\tlinkOriginPropertyName = %@;\n\tindexed = %@;\n\tisPrimary = %@;\n\toptional = %@;\n}", self.name, RLMTypeToString(self.type), self.objectClassName, self.linkOriginPropertyName, self.indexed ? @"YES" : @"NO", self.isPrimary ? @"YES" : @"NO", self.optional ? @"YES" : @"NO"]; -} - -- (realm::Property)objectStoreCopy { - realm::Property p; - p.name = _name.UTF8String; - p.type = (realm::PropertyType)_type; - p.object_type = _objectClassName ? _objectClassName.UTF8String : ""; - p.is_indexed = _indexed; - p.is_nullable = _optional; - p.link_origin_property_name = _linkOriginPropertyName ? _linkOriginPropertyName.UTF8String : ""; - return p; -} - -@end - -@implementation RLMPropertyDescriptor - -+ (instancetype)descriptorWithClass:(Class)objectClass propertyName:(NSString *)propertyName -{ - RLMPropertyDescriptor *descriptor = [[RLMPropertyDescriptor alloc] init]; - descriptor->_objectClass = objectClass; - descriptor->_propertyName = propertyName; - return descriptor; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMQueryUtil.mm b/Example/Pods/Realm/Realm/RLMQueryUtil.mm deleted file mode 100644 index 22de53c..0000000 --- a/Example/Pods/Realm/Realm/RLMQueryUtil.mm +++ /dev/null @@ -1,1381 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMQueryUtil.hpp" - -#import "RLMArray.h" -#import "RLMObjectSchema_Private.h" -#import "RLMObject_Private.hpp" -#import "RLMPredicateUtil.hpp" -#import "RLMProperty.h" -#import "RLMSchema.h" -#import "RLMUtil.hpp" - -#import "object_store.hpp" -#import "results.hpp" - -#include - -using namespace realm; - -NSString * const RLMPropertiesComparisonTypeMismatchException = @"RLMPropertiesComparisonTypeMismatchException"; -NSString * const RLMUnsupportedTypesFoundInPropertyComparisonException = @"RLMUnsupportedTypesFoundInPropertyComparisonException"; - -NSString * const RLMPropertiesComparisonTypeMismatchReason = @"Property type mismatch between %@ and %@"; -NSString * const RLMUnsupportedTypesFoundInPropertyComparisonReason = @"Comparison between %@ and %@"; - -// small helper to create the many exceptions thrown when parsing predicates -static NSException *RLMPredicateException(NSString *name, NSString *format, ...) { - va_list args; - va_start(args, format); - NSString *reason = [[NSString alloc] initWithFormat:format arguments:args]; - va_end(args); - - return [NSException exceptionWithName:name reason:reason userInfo:nil]; -} - -// check a precondition and throw an exception if it is not met -// this should be used iff the condition being false indicates a bug in the caller -// of the function checking its preconditions -static void RLMPrecondition(bool condition, NSString *name, NSString *format, ...) { - if (__builtin_expect(condition, 1)) { - return; - } - - va_list args; - va_start(args, format); - NSString *reason = [[NSString alloc] initWithFormat:format arguments:args]; - va_end(args); - - @throw [NSException exceptionWithName:name reason:reason userInfo:nil]; -} - -// return the property for a validated column name -RLMProperty *RLMValidatedProperty(RLMObjectSchema *desc, NSString *columnName) { - RLMProperty *prop = desc[columnName]; - RLMPrecondition(prop, @"Invalid property name", - @"Property '%@' not found in object of type '%@'", columnName, desc.className); - return prop; -} - -namespace { -BOOL RLMPropertyTypeIsNumeric(RLMPropertyType propertyType) { - switch (propertyType) { - case RLMPropertyTypeInt: - case RLMPropertyTypeFloat: - case RLMPropertyTypeDouble: - return YES; - default: - return NO; - } -} - -// FIXME: TrueExpression and FalseExpression should be supported by core in some way - -struct TrueExpression : realm::Expression { - size_t find_first(size_t start, size_t end) const override - { - if (start != end) - return start; - - return realm::not_found; - } - void set_base_table(const Table*) override {} - const Table* get_base_table() const override { return nullptr; } - std::unique_ptr clone(QueryNodeHandoverPatches*) const override - { - return std::unique_ptr(new TrueExpression(*this)); - } -}; - -struct FalseExpression : realm::Expression { - size_t find_first(size_t, size_t) const override { return realm::not_found; } - void set_base_table(const Table*) override {} - const Table* get_base_table() const override { return nullptr; } - std::unique_ptr clone(QueryNodeHandoverPatches*) const override - { - return std::unique_ptr(new FalseExpression(*this)); - } -}; - -NSString *operatorName(NSPredicateOperatorType operatorType) -{ - switch (operatorType) { - case NSLessThanPredicateOperatorType: - return @"<"; - case NSLessThanOrEqualToPredicateOperatorType: - return @"<="; - case NSGreaterThanPredicateOperatorType: - return @">"; - case NSGreaterThanOrEqualToPredicateOperatorType: - return @">="; - case NSEqualToPredicateOperatorType: - return @"=="; - case NSNotEqualToPredicateOperatorType: - return @"!="; - case NSMatchesPredicateOperatorType: - return @"MATCHES"; - case NSLikePredicateOperatorType: - return @"LIKE"; - case NSBeginsWithPredicateOperatorType: - return @"BEGINSWITH"; - case NSEndsWithPredicateOperatorType: - return @"ENDSWITH"; - case NSInPredicateOperatorType: - return @"IN"; - case NSContainsPredicateOperatorType: - return @"CONTAINS"; - case NSBetweenPredicateOperatorType: - return @"BETWEEN"; - case NSCustomSelectorPredicateOperatorType: - return @"custom selector"; - } - - return [NSString stringWithFormat:@"unknown operator %lu", (unsigned long)operatorType]; -} - -Table& get_table(Group& group, RLMObjectSchema *objectSchema) -{ - return *ObjectStore::table_for_object_type(group, objectSchema.objectName.UTF8String); -} - -// A reference to a column within a query. Can be resolved to a Columns for use in query expressions. -class ColumnReference { -public: - ColumnReference(Query& query, Group& group, RLMSchema *schema, RLMProperty* property, const std::vector& links = {}) - : m_links(links), m_property(property), m_schema(schema), m_group(&group), m_query(&query), m_table(query.get_table().get()) - { - auto& table = walk_link_chain([](Table&, size_t, RLMPropertyType) { }); - m_index = table.get_column_index(m_property.name.UTF8String); - } - - template - auto resolve(SubQuery&&... subquery) const - { - static_assert(sizeof...(SubQuery) < 2, "resolve() takes at most one subquery"); - set_link_chain_on_table(); - if (type() != RLMPropertyTypeLinkingObjects) { - return m_table->template column(index(), std::forward(subquery)...); - } - else { - return resolve_backlink(std::forward(subquery)...); - } - } - - RLMProperty *property() const { return m_property; } - size_t index() const { return m_index; } - RLMPropertyType type() const { return property().type; } - Group& group() const { return *m_group; } - - RLMObjectSchema *link_target_object_schema() const - { - switch (type()) { - case RLMPropertyTypeObject: - case RLMPropertyTypeArray: - case RLMPropertyTypeLinkingObjects: - return m_schema[property().objectClassName]; - default: - REALM_ASSERT(false); - } - } - - bool has_links() const { return m_links.size(); } - - bool has_any_to_many_links() const { - return std::any_of(begin(m_links), end(m_links), [](RLMProperty *property) { - return property.type == RLMPropertyTypeArray || property.type == RLMPropertyTypeLinkingObjects; - }); - } - - ColumnReference last_link_column() const { - REALM_ASSERT(!m_links.empty()); - return {*m_query, *m_group, m_schema, m_links.back(), {m_links.begin(), m_links.end() - 1}}; - } - - ColumnReference column_ignoring_links(Query& query) const { - return {query, *m_group, m_schema, m_property}; - } - -private: - template - auto resolve_backlink(SubQuery&&... subquery) const - { - // We actually just want `if constexpr (std::is_same::value) { ... }`, - // so fake it by tag-dispatching on the conditional - return do_resolve_backlink(std::is_same(), std::forward(subquery)...); - } - - template - auto do_resolve_backlink(std::true_type, SubQuery&&... subquery) const - { - return with_link_origin(m_property, [&](Table& table, size_t col) { - return m_table->template column(table, col, std::forward(subquery)...); - }); - } - - template - Columns do_resolve_backlink(std::false_type, SubQuery&&...) const - { - // This can't actually happen as we only call resolve_backlink() if - // it's RLMPropertyTypeLinkingObjects - __builtin_unreachable(); - } - - template - Table& walk_link_chain(Func&& func) const - { - auto table = m_query->get_table().get(); - for (const auto& link : m_links) { - if (link.type != RLMPropertyTypeLinkingObjects) { - auto index = table->get_column_index(link.name.UTF8String); - func(*table, index, link.type); - table = table->get_link_target(index).get(); - } - else { - with_link_origin(link, [&](Table& link_origin_table, size_t link_origin_column) { - func(link_origin_table, link_origin_column, link.type); - table = &link_origin_table; - }); - } - } - return *table; - } - - template - auto with_link_origin(RLMProperty *prop, Func&& func) const - { - RLMObjectSchema *link_origin_schema = m_schema[prop.objectClassName]; - Table& link_origin_table = get_table(*m_group, link_origin_schema); - size_t link_origin_column = link_origin_table.get_column_index(prop.linkOriginPropertyName.UTF8String); - return func(link_origin_table, link_origin_column); - } - - void set_link_chain_on_table() const - { - walk_link_chain([&](Table& current_table, size_t column, RLMPropertyType type) { - if (type == RLMPropertyTypeLinkingObjects) { - m_table->backlink(current_table, column); - } - else { - m_table->link(column); - } - }); - } - - std::vector m_links; - RLMProperty *m_property; - RLMSchema *m_schema; - Group *m_group; - Query *m_query; - Table *m_table; - size_t m_index; -}; - -class CollectionOperation { -public: - enum Type { - Count, - Minimum, - Maximum, - Sum, - Average, - }; - - CollectionOperation(Type type, ColumnReference link_column, util::Optional column) - : m_type(type) - , m_link_column(std::move(link_column)) - , m_column(std::move(column)) - { - RLMPrecondition(m_link_column.type() == RLMPropertyTypeArray || m_link_column.type() == RLMPropertyTypeLinkingObjects, - @"Invalid predicate", @"Collection operation can only be applied to a property of type RLMArray."); - - switch (m_type) { - case Count: - RLMPrecondition(!m_column, @"Invalid predicate", @"Result of @count does not have any properties."); - break; - case Minimum: - case Maximum: - case Sum: - case Average: - RLMPrecondition(m_column && RLMPropertyTypeIsNumeric(m_column->type()), @"Invalid predicate", - @"%@ can only be applied to a numeric property.", name_for_type(m_type)); - break; - } - } - - CollectionOperation(NSString *operationName, ColumnReference link_column, util::Optional column = util::none) - : CollectionOperation(type_for_name(operationName), std::move(link_column), std::move(column)) - { - } - - Type type() const { return m_type; } - const ColumnReference& link_column() const { return m_link_column; } - const ColumnReference& column() const { return *m_column; } - - void validate_comparison(id value) const { - switch (m_type) { - case Count: - case Average: - RLMPrecondition([value isKindOfClass:[NSNumber class]], @"Invalid operand", - @"%@ can only be compared with a numeric value.", name_for_type(m_type)); - break; - case Minimum: - case Maximum: - case Sum: - RLMPrecondition(RLMIsObjectValidForProperty(value, m_column->property()), @"Invalid operand", - @"%@ on a property of type %@ cannot be compared with '%@'", - name_for_type(m_type), RLMTypeToString(m_column->type()), value); - break; - } - } - - void validate_comparison(const ColumnReference& column) const { - switch (m_type) { - case Count: - RLMPrecondition(RLMPropertyTypeIsNumeric(column.type()), @"Invalid operand", - @"%@ can only be compared with a numeric value.", name_for_type(m_type)); - break; - case Average: - case Minimum: - case Maximum: - case Sum: - RLMPrecondition(RLMPropertyTypeIsNumeric(column.type()), @"Invalid operand", - @"%@ on a property of type %@ cannot be compared with property of type '%@'", - name_for_type(m_type), RLMTypeToString(m_column->type()), RLMTypeToString(column.type())); - break; - } - } - -private: - static Type type_for_name(NSString *name) { - if ([name isEqualToString:@"@count"]) { - return Count; - } - if ([name isEqualToString:@"@min"]) { - return Minimum; - } - if ([name isEqualToString:@"@max"]) { - return Maximum; - } - if ([name isEqualToString:@"@sum"]) { - return Sum; - } - if ([name isEqualToString:@"@avg"]) { - return Average; - } - @throw RLMPredicateException(@"Invalid predicate", @"Unsupported collection operation '%@'", name); - } - - static NSString *name_for_type(Type type) { - switch (type) { - case Count: return @"@count"; - case Minimum: return @"@min"; - case Maximum: return @"@max"; - case Sum: return @"@sum"; - case Average: return @"@avg"; - } - } - - Type m_type; - ColumnReference m_link_column; - util::Optional m_column; -}; - -class QueryBuilder { -public: - QueryBuilder(Query& query, Group& group, RLMSchema *schema) - : m_query(query), m_group(group), m_schema(schema) { } - - void apply_predicate(NSPredicate *predicate, RLMObjectSchema *objectSchema); - - - void apply_collection_operator_expression(RLMObjectSchema *desc, NSString *keyPath, id value, NSComparisonPredicate *pred); - void apply_value_expression(RLMObjectSchema *desc, NSString *keyPath, id value, NSComparisonPredicate *pred); - void apply_column_expression(RLMObjectSchema *desc, NSString *leftKeyPath, NSString *rightKeyPath, NSComparisonPredicate *predicate); - void apply_subquery_count_expression(RLMObjectSchema *objectSchema, NSExpression *subqueryExpression, - NSPredicateOperatorType operatorType, NSExpression *right); - void apply_function_subquery_expression(RLMObjectSchema *objectSchema, NSExpression *functionExpression, - NSPredicateOperatorType operatorType, NSExpression *right); - void apply_function_expression(RLMObjectSchema *objectSchema, NSExpression *functionExpression, - NSPredicateOperatorType operatorType, NSExpression *right); - - - template - void add_numeric_constraint(RLMPropertyType datatype, - NSPredicateOperatorType operatorType, - A&& lhs, B&& rhs); - - template - void add_bool_constraint(NSPredicateOperatorType operatorType, A lhs, B rhs); - - template - void add_string_constraint(NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, - Columns &&column, - T value); - - void add_string_constraint(NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, - StringData value, - Columns&& column); - - template - void add_constraint(RLMPropertyType type, - NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, - L lhs, R rhs); - template - void do_add_constraint(RLMPropertyType type, NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, T... values); - void do_add_constraint(RLMPropertyType, NSPredicateOperatorType, NSComparisonPredicateOptions, id, realm::null); - - void add_between_constraint(const ColumnReference& column, id value); - - template - void add_binary_constraint(NSPredicateOperatorType operatorType, const ColumnReference& column, T value); - void add_binary_constraint(NSPredicateOperatorType operatorType, const ColumnReference& column, id value); - void add_binary_constraint(NSPredicateOperatorType operatorType, id value, const ColumnReference& column); - void add_binary_constraint(NSPredicateOperatorType, const ColumnReference&, const ColumnReference&); - - void add_link_constraint(NSPredicateOperatorType operatorType, const ColumnReference& column, RLMObject *obj); - void add_link_constraint(NSPredicateOperatorType operatorType, const ColumnReference& column, realm::null); - template - void add_link_constraint(NSPredicateOperatorType operatorType, T obj, const ColumnReference& column); - void add_link_constraint(NSPredicateOperatorType, const ColumnReference&, const ColumnReference&); - - template - void add_collection_operation_constraint(RLMPropertyType propertyType, NSPredicateOperatorType operatorType, T... values); - template - void add_collection_operation_constraint(NSPredicateOperatorType operatorType, - CollectionOperation collectionOperation, T... values); - - - CollectionOperation collection_operation_from_key_path(RLMObjectSchema *desc, NSString *keyPath); - ColumnReference column_reference_from_key_path(RLMObjectSchema *objectSchema, NSString *keyPath, bool isAggregate); - -private: - Query& m_query; - Group& m_group; - RLMSchema *m_schema; -}; - -// add a clause for numeric constraints based on operator type -template -void QueryBuilder::add_numeric_constraint(RLMPropertyType datatype, - NSPredicateOperatorType operatorType, - A&& lhs, B&& rhs) -{ - switch (operatorType) { - case NSLessThanPredicateOperatorType: - m_query.and_query(lhs < rhs); - break; - case NSLessThanOrEqualToPredicateOperatorType: - m_query.and_query(lhs <= rhs); - break; - case NSGreaterThanPredicateOperatorType: - m_query.and_query(lhs > rhs); - break; - case NSGreaterThanOrEqualToPredicateOperatorType: - m_query.and_query(lhs >= rhs); - break; - case NSEqualToPredicateOperatorType: - m_query.and_query(lhs == rhs); - break; - case NSNotEqualToPredicateOperatorType: - m_query.and_query(lhs != rhs); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' not supported for type %@", operatorName(operatorType), RLMTypeToString(datatype)); - } -} - -template -void QueryBuilder::add_bool_constraint(NSPredicateOperatorType operatorType, A lhs, B rhs) { - switch (operatorType) { - case NSEqualToPredicateOperatorType: - m_query.and_query(lhs == rhs); - break; - case NSNotEqualToPredicateOperatorType: - m_query.and_query(lhs != rhs); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' not supported for bool type", operatorName(operatorType)); - } -} - -template -void QueryBuilder::add_string_constraint(NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, - Columns &&column, - T value) { - bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption); - bool diacriticInsensitive = (predicateOptions & NSDiacriticInsensitivePredicateOption); - RLMPrecondition(!diacriticInsensitive, @"Invalid predicate option", - @"NSDiacriticInsensitivePredicateOption not supported for string type"); - - switch (operatorType) { - case NSBeginsWithPredicateOperatorType: - m_query.and_query(column.begins_with(value, caseSensitive)); - break; - case NSEndsWithPredicateOperatorType: - m_query.and_query(column.ends_with(value, caseSensitive)); - break; - case NSContainsPredicateOperatorType: - m_query.and_query(column.contains(value, caseSensitive)); - break; - case NSEqualToPredicateOperatorType: - m_query.and_query(column.equal(value, caseSensitive)); - break; - case NSNotEqualToPredicateOperatorType: - m_query.and_query(column.not_equal(value, caseSensitive)); - break; - case NSLikePredicateOperatorType: - m_query.and_query(column.like(value, caseSensitive)); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' not supported for string type", operatorName(operatorType)); - } -} - -void QueryBuilder::add_string_constraint(NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, - StringData value, - Columns&& column) { - switch (operatorType) { - case NSEqualToPredicateOperatorType: - case NSNotEqualToPredicateOperatorType: - add_string_constraint(operatorType, predicateOptions, std::move(column), value); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' is not supported for string type with key path on right side of operator", - operatorName(operatorType)); - } -} - -id value_from_constant_expression_or_value(id value) { - if (NSExpression *exp = RLMDynamicCast(value)) { - RLMPrecondition(exp.expressionType == NSConstantValueExpressionType, - @"Invalid value", - @"Expressions within predicate aggregates must be constant values"); - return exp.constantValue; - } - return value; -} - -void validate_and_extract_between_range(id value, RLMProperty *prop, id *from, id *to) { - NSArray *array = RLMDynamicCast(value); - RLMPrecondition(array, @"Invalid value", @"object must be of type NSArray for BETWEEN operations"); - RLMPrecondition(array.count == 2, @"Invalid value", @"NSArray object must contain exactly two objects for BETWEEN operations"); - - *from = value_from_constant_expression_or_value(array.firstObject); - *to = value_from_constant_expression_or_value(array.lastObject); - RLMPrecondition(RLMIsObjectValidForProperty(*from, prop) && RLMIsObjectValidForProperty(*to, prop), - @"Invalid value", - @"NSArray objects must be of type %@ for BETWEEN operations", RLMTypeToString(prop.type)); -} - -void QueryBuilder::add_between_constraint(const ColumnReference& column, id value) { - if (column.has_any_to_many_links()) { - auto link_column = column.last_link_column(); - Query subquery = get_table(m_group, link_column.link_target_object_schema()).where(); - QueryBuilder(subquery, m_group, m_schema).add_between_constraint(column.column_ignoring_links(subquery), value); - - m_query.and_query(link_column.resolve(std::move(subquery)).count() > 0); - return; - } - - id from, to; - validate_and_extract_between_range(value, column.property(), &from, &to); - - RLMPropertyType type = column.type(); - - m_query.group(); - add_constraint(type, NSGreaterThanOrEqualToPredicateOperatorType, 0, column, from); - add_constraint(type, NSLessThanOrEqualToPredicateOperatorType, 0, column, to); - m_query.end_group(); -} - -template -void QueryBuilder::add_binary_constraint(NSPredicateOperatorType operatorType, - const ColumnReference& column, - T value) { - RLMPrecondition(!column.has_links(), @"Unsupported operator", @"NSData properties cannot be queried over an object link."); - - size_t index = column.index(); - switch (operatorType) { - case NSBeginsWithPredicateOperatorType: - m_query.begins_with(index, value); - break; - case NSEndsWithPredicateOperatorType: - m_query.ends_with(index, value); - break; - case NSContainsPredicateOperatorType: - m_query.contains(index, value); - break; - case NSEqualToPredicateOperatorType: - m_query.equal(index, value); - break; - case NSNotEqualToPredicateOperatorType: - m_query.not_equal(index, value); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' not supported for binary type", operatorName(operatorType)); - } -} - -void QueryBuilder::add_binary_constraint(NSPredicateOperatorType operatorType, const ColumnReference& column, id value) { - add_binary_constraint(operatorType, column, RLMBinaryDataForNSData(value)); -} - -void QueryBuilder::add_binary_constraint(NSPredicateOperatorType operatorType, id value, const ColumnReference& column) { - switch (operatorType) { - case NSEqualToPredicateOperatorType: - case NSNotEqualToPredicateOperatorType: - add_binary_constraint(operatorType, column, value); - break; - default: - @throw RLMPredicateException(@"Invalid operator type", - @"Operator '%@' is not supported for binary type with key path on right side of operator", - operatorName(operatorType)); - } -} - -void QueryBuilder::add_binary_constraint(NSPredicateOperatorType, const ColumnReference&, const ColumnReference&) { - @throw RLMPredicateException(@"Invalid predicate", @"Comparisons between two NSData properties are not supported"); -} - -void QueryBuilder::add_link_constraint(NSPredicateOperatorType operatorType, - const ColumnReference& column, RLMObject *obj) { - RLMPrecondition(operatorType == NSEqualToPredicateOperatorType || operatorType == NSNotEqualToPredicateOperatorType, - @"Invalid operator type", @"Only 'Equal' and 'Not Equal' operators supported for object comparison"); - - if (operatorType == NSEqualToPredicateOperatorType) { - m_query.and_query(column.resolve() == obj->_row); - } - else { - m_query.and_query(column.resolve() != obj->_row); - } -} - -void QueryBuilder::add_link_constraint(NSPredicateOperatorType operatorType, - const ColumnReference& column, - realm::null) { - RLMPrecondition(!column.has_links(), @"Unsupported operator", @"Multi-level object equality link queries are not supported."); - RLMPrecondition(operatorType == NSEqualToPredicateOperatorType || operatorType == NSNotEqualToPredicateOperatorType, - @"Invalid operator type", @"Only 'Equal' and 'Not Equal' operators supported for object comparison"); - if (operatorType == NSNotEqualToPredicateOperatorType) { - m_query.Not(); - } - - m_query.and_query(column.resolve().is_null()); -} - -template -void QueryBuilder::add_link_constraint(NSPredicateOperatorType operatorType, T obj, const ColumnReference& column) { - // Link constraints only support the equal-to and not-equal-to operators. The order of operands - // is not important for those comparisons so we can delegate to the other implementation. - add_link_constraint(operatorType, column, obj); -} - -void QueryBuilder::add_link_constraint(NSPredicateOperatorType, const ColumnReference&, const ColumnReference&) { - // This is not actually reachable as this case is caught earlier, but this - // overload is needed for the code to compile - @throw RLMPredicateException(@"Invalid predicate", @"Comparisons between two RLMArray properties are not supported"); -} - - -// iterate over an array of subpredicates, using @func to build a query from each -// one and ORing them together -template -void process_or_group(Query &query, id array, Func&& func) { - RLMPrecondition([array conformsToProtocol:@protocol(NSFastEnumeration)], - @"Invalid value", @"IN clause requires an array of items"); - - query.group(); - - bool first = true; - for (id item in array) { - if (!first) { - query.Or(); - } - first = false; - - func(item); - } - - if (first) { - // Queries can't be empty, so if there's zero things in the OR group - // validation will fail. Work around this by adding an expression which - // will never find any rows in a table. - query.and_query(std::unique_ptr(new FalseExpression)); - } - - query.end_group(); -} - -template -RequestedType convert(id value); - -template <> -Timestamp convert(id value) { - return RLMTimestampForNSDate(value); -} - -template <> -bool convert(id value) { - return [value boolValue]; -} - -template <> -Double convert(id value) { - return [value doubleValue]; -} - -template <> -Float convert(id value) { - return [value floatValue]; -} - -template <> -Int convert(id value) { - return [value longLongValue]; -} - -template <> -String convert(id value) { - return RLMStringDataWithNSString(value); -} - -template -realm::null value_of_type(realm::null) { - return realm::null(); -} - -template -auto value_of_type(id value) { - return ::convert(value); -} - -template -auto value_of_type(const ColumnReference& column) { - return column.resolve(); -} - - -template -void QueryBuilder::do_add_constraint(RLMPropertyType type, NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, T... values) -{ - static_assert(sizeof...(T) == 2, "do_add_constraint accepts only two values as arguments"); - - switch (type) { - case RLMPropertyTypeBool: - add_bool_constraint(operatorType, value_of_type(values)...); - break; - case RLMPropertyTypeDate: - add_numeric_constraint(type, operatorType, value_of_type(values)...); - break; - case RLMPropertyTypeDouble: - add_numeric_constraint(type, operatorType, value_of_type(values)...); - break; - case RLMPropertyTypeFloat: - add_numeric_constraint(type, operatorType, value_of_type(values)...); - break; - case RLMPropertyTypeInt: - add_numeric_constraint(type, operatorType, value_of_type(values)...); - break; - case RLMPropertyTypeString: - add_string_constraint(operatorType, predicateOptions, value_of_type(values)...); - break; - case RLMPropertyTypeData: - add_binary_constraint(operatorType, values...); - break; - case RLMPropertyTypeObject: - case RLMPropertyTypeArray: - case RLMPropertyTypeLinkingObjects: - add_link_constraint(operatorType, values...); - break; - default: - @throw RLMPredicateException(@"Unsupported predicate value type", - @"Object type %@ not supported", RLMTypeToString(type)); - } -} - -void QueryBuilder::do_add_constraint(RLMPropertyType, NSPredicateOperatorType, NSComparisonPredicateOptions, id, realm::null) -{ - // This is not actually reachable as this case is caught earlier, but this - // overload is needed for the code to compile - @throw RLMPredicateException(@"Invalid predicate expressions", - @"Predicate expressions must compare a keypath and another keypath or a constant value"); -} - -bool is_nsnull(id value) { - return !value || value == NSNull.null; -} - -template -bool is_nsnull(T) { - return false; -} - -template -void QueryBuilder::add_constraint(RLMPropertyType type, NSPredicateOperatorType operatorType, - NSComparisonPredicateOptions predicateOptions, L lhs, R rhs) -{ - // The expression operators are only overloaded for realm::null on the rhs - RLMPrecondition(!is_nsnull(lhs), @"Unsupported operator", - @"Nil is only supported on the right side of operators"); - - if (is_nsnull(rhs)) { - do_add_constraint(type, operatorType, predicateOptions, lhs, realm::null()); - } - else { - do_add_constraint(type, operatorType, predicateOptions, lhs, rhs); - } -} - -ColumnReference QueryBuilder::column_reference_from_key_path(RLMObjectSchema *objectSchema, NSString *keyPath, bool isAggregate) -{ - RLMProperty *property; - std::vector links; - - bool keyPathContainsToManyRelationship = false; - - NSUInteger start = 0, length = keyPath.length, end = NSNotFound; - do { - end = [keyPath rangeOfString:@"." options:0 range:{start, length - start}].location; - NSString *propertyName = [keyPath substringWithRange:{start, end == NSNotFound ? length - start : end - start}]; - property = objectSchema[propertyName]; - RLMPrecondition(property, @"Invalid property name", - @"Property '%@' not found in object of type '%@'", propertyName, objectSchema.className); - - if (property.type == RLMPropertyTypeArray || property.type == RLMPropertyTypeLinkingObjects) - keyPathContainsToManyRelationship = true; - - if (end != NSNotFound) { - RLMPrecondition(property.type == RLMPropertyTypeObject || property.type == RLMPropertyTypeArray || property.type == RLMPropertyTypeLinkingObjects, - @"Invalid value", @"Property '%@' is not a link in object of type '%@'", propertyName, objectSchema.className); - - links.push_back(property); - REALM_ASSERT(property.objectClassName); - objectSchema = m_schema[property.objectClassName]; - } - - start = end + 1; - } while (end != NSNotFound); - - if (isAggregate && !keyPathContainsToManyRelationship) { - @throw RLMPredicateException(@"Invalid predicate", - @"Aggregate operations can only be used on key paths that include an array property"); - } else if (!isAggregate && keyPathContainsToManyRelationship) { - @throw RLMPredicateException(@"Invalid predicate", - @"Key paths that include an array property must use aggregate operations"); - } - - return ColumnReference(m_query, m_group, m_schema, property, std::move(links)); -} - -void validate_property_value(const ColumnReference& column, - __unsafe_unretained id const value, - __unsafe_unretained NSString *const err, - __unsafe_unretained RLMObjectSchema *const objectSchema, - __unsafe_unretained NSString *const keyPath) { - RLMProperty *prop = column.property(); - if (prop.type == RLMPropertyTypeArray) { - RLMPrecondition([RLMObjectBaseObjectSchema(RLMDynamicCast(value)).className isEqualToString:prop.objectClassName], - @"Invalid value", err, prop.objectClassName, keyPath, objectSchema.className, value); - } - else { - RLMPrecondition(RLMIsObjectValidForProperty(value, prop), - @"Invalid value", err, RLMTypeToString(prop.type), keyPath, objectSchema.className, value); - } - if (RLMObjectBase *obj = RLMDynamicCast(value)) { - RLMPrecondition(!obj->_row.is_attached() || &column.group() == &obj->_realm.group, - @"Invalid value origin", @"Object must be from the Realm being queried"); - } -} - -template -struct ValueOfTypeWithCollectionOperationHelper; - -template <> -struct ValueOfTypeWithCollectionOperationHelper { - static auto convert(const CollectionOperation& operation) - { - assert(operation.type() == CollectionOperation::Count); - return operation.link_column().resolve().count(); - } -}; - -#define VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER(OperationType, function) \ -template \ -struct ValueOfTypeWithCollectionOperationHelper { \ - static auto convert(const CollectionOperation& operation) \ - { \ - REALM_ASSERT(operation.type() == OperationType); \ - auto targetColumn = operation.link_column().resolve().template column(operation.column().index()); \ - return targetColumn.function(); \ - } \ -} \ - -VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER(CollectionOperation::Minimum, min); -VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER(CollectionOperation::Maximum, max); -VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER(CollectionOperation::Sum, sum); -VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER(CollectionOperation::Average, average); -#undef VALUE_OF_TYPE_WITH_COLLECTION_OPERATOR_HELPER - -template -auto value_of_type_with_collection_operation(T&& value) { - return value_of_type(std::forward(value)); -} - -template -auto value_of_type_with_collection_operation(CollectionOperation operation) { - using helper = ValueOfTypeWithCollectionOperationHelper; - return helper::convert(operation); -} - -template -void QueryBuilder::add_collection_operation_constraint(RLMPropertyType propertyType, NSPredicateOperatorType operatorType, T... values) -{ - switch (propertyType) { - case RLMPropertyTypeInt: - add_numeric_constraint(propertyType, operatorType, value_of_type_with_collection_operation(values)...); - break; - case RLMPropertyTypeFloat: - add_numeric_constraint(propertyType, operatorType, value_of_type_with_collection_operation(values)...); - break; - case RLMPropertyTypeDouble: - add_numeric_constraint(propertyType, operatorType, value_of_type_with_collection_operation(values)...); - break; - default: - REALM_ASSERT(false && "Only numeric property types should hit this path."); - } -} - -template -void QueryBuilder::add_collection_operation_constraint(NSPredicateOperatorType operatorType, - CollectionOperation collectionOperation, T... values) -{ - static_assert(sizeof...(T) == 2, "add_collection_operation_constraint accepts only two values as arguments"); - - switch (collectionOperation.type()) { - case CollectionOperation::Count: - add_numeric_constraint(RLMPropertyTypeInt, operatorType, - value_of_type_with_collection_operation(values)...); - break; - case CollectionOperation::Minimum: - add_collection_operation_constraint(collectionOperation.column().type(), operatorType, values...); - break; - case CollectionOperation::Maximum: - add_collection_operation_constraint(collectionOperation.column().type(), operatorType, values...); - break; - case CollectionOperation::Sum: - add_collection_operation_constraint(collectionOperation.column().type(), operatorType, values...); - break; - case CollectionOperation::Average: - add_collection_operation_constraint(collectionOperation.column().type(), operatorType, values...); - break; - } -} - -bool key_path_contains_collection_operator(NSString *keyPath) { - return [keyPath rangeOfString:@"@"].location != NSNotFound; -} - -NSString *get_collection_operation_name_from_key_path(NSString *keyPath, NSString **leadingKeyPath, NSString **trailingKey) { - NSRange at = [keyPath rangeOfString:@"@"]; - if (at.location == NSNotFound || at.location >= keyPath.length - 1) { - @throw RLMPredicateException(@"Invalid key path", @"'%@' is not a valid key path'", keyPath); - } - - if (at.location == 0 || [keyPath characterAtIndex:at.location - 1] != '.') { - @throw RLMPredicateException(@"Invalid key path", @"'%@' is not a valid key path'", keyPath); - } - - NSRange trailingKeyRange = [keyPath rangeOfString:@"." options:0 range:{at.location, keyPath.length - at.location} locale:nil]; - - *leadingKeyPath = [keyPath substringToIndex:at.location - 1]; - if (trailingKeyRange.location == NSNotFound) { - *trailingKey = nil; - return [keyPath substringFromIndex:at.location]; - } else { - *trailingKey = [keyPath substringFromIndex:trailingKeyRange.location + 1]; - return [keyPath substringWithRange:{at.location, trailingKeyRange.location - at.location}]; - } -} - -CollectionOperation QueryBuilder::collection_operation_from_key_path(RLMObjectSchema *desc, NSString *keyPath) { - NSString *leadingKeyPath; - NSString *trailingKey; - NSString *collectionOperationName = get_collection_operation_name_from_key_path(keyPath, &leadingKeyPath, &trailingKey); - - ColumnReference linkColumn = column_reference_from_key_path(desc, leadingKeyPath, true); - util::Optional column; - if (trailingKey) { - RLMPrecondition([trailingKey rangeOfString:@"."].location == NSNotFound, @"Invalid key path", - @"Right side of collection operator may only have a single level key"); - NSString *fullKeyPath = [leadingKeyPath stringByAppendingFormat:@".%@", trailingKey]; - column = column_reference_from_key_path(desc, fullKeyPath, true); - } - - return {collectionOperationName, std::move(linkColumn), std::move(column)}; -} - -void QueryBuilder::apply_collection_operator_expression(RLMObjectSchema *desc, - NSString *keyPath, id value, - NSComparisonPredicate *pred) { - CollectionOperation operation = collection_operation_from_key_path(desc, keyPath); - operation.validate_comparison(value); - - if (pred.leftExpression.expressionType == NSKeyPathExpressionType) { - add_collection_operation_constraint(pred.predicateOperatorType, operation, operation, value); - } else { - add_collection_operation_constraint(pred.predicateOperatorType, operation, value, operation); - } -} - -void QueryBuilder::apply_value_expression(RLMObjectSchema *desc, - NSString *keyPath, id value, - NSComparisonPredicate *pred) -{ - if (key_path_contains_collection_operator(keyPath)) { - apply_collection_operator_expression(desc, keyPath, value, pred); - return; - } - - bool isAny = pred.comparisonPredicateModifier == NSAnyPredicateModifier; - ColumnReference column = column_reference_from_key_path(desc, keyPath, isAny); - - // check to see if this is a between query - if (pred.predicateOperatorType == NSBetweenPredicateOperatorType) { - add_between_constraint(std::move(column), value); - return; - } - - // turn "key.path IN collection" into ored together ==. "collection IN key.path" is handled elsewhere. - if (pred.predicateOperatorType == NSInPredicateOperatorType) { - process_or_group(m_query, value, [&](id item) { - id normalized = value_from_constant_expression_or_value(item); - validate_property_value(column, normalized, - @"Expected object of type %@ in IN clause for property '%@' on object of type '%@', but received: %@", desc, keyPath); - add_constraint(column.type(), NSEqualToPredicateOperatorType, pred.options, column, normalized); - }); - return; - } - - validate_property_value(column, value, @"Expected object of type %@ for property '%@' on object of type '%@', but received: %@", desc, keyPath); - if (pred.leftExpression.expressionType == NSKeyPathExpressionType) { - add_constraint(column.type(), pred.predicateOperatorType, pred.options, std::move(column), value); - } else { - add_constraint(column.type(), pred.predicateOperatorType, pred.options, value, std::move(column)); - } -} - -void QueryBuilder::apply_column_expression(RLMObjectSchema *desc, - NSString *leftKeyPath, NSString *rightKeyPath, - NSComparisonPredicate *predicate) -{ - bool left_key_path_contains_collection_operator = key_path_contains_collection_operator(leftKeyPath); - bool right_key_path_contains_collection_operator = key_path_contains_collection_operator(rightKeyPath); - if (left_key_path_contains_collection_operator && right_key_path_contains_collection_operator) { - @throw RLMPredicateException(@"Unsupported predicate", @"Key paths including aggregate operations cannot be compared with other aggregate operations."); - } - - if (left_key_path_contains_collection_operator) { - CollectionOperation left = collection_operation_from_key_path(desc, leftKeyPath); - ColumnReference right = column_reference_from_key_path(desc, rightKeyPath, false); - left.validate_comparison(right); - add_collection_operation_constraint(predicate.predicateOperatorType, left, left, std::move(right)); - return; - } - if (right_key_path_contains_collection_operator) { - ColumnReference left = column_reference_from_key_path(desc, leftKeyPath, false); - CollectionOperation right = collection_operation_from_key_path(desc, rightKeyPath); - right.validate_comparison(left); - add_collection_operation_constraint(predicate.predicateOperatorType, right, std::move(left), right); - return; - } - - bool isAny = false; - ColumnReference left = column_reference_from_key_path(desc, leftKeyPath, isAny); - ColumnReference right = column_reference_from_key_path(desc, rightKeyPath, isAny); - - // NOTE: It's assumed that column type must match and no automatic type conversion is supported. - RLMPrecondition(left.type() == right.type(), - RLMPropertiesComparisonTypeMismatchException, - RLMPropertiesComparisonTypeMismatchReason, - RLMTypeToString(left.type()), - RLMTypeToString(right.type())); - - // TODO: Should we handle special case where left row is the same as right row (tautology) - add_constraint(left.type(), predicate.predicateOperatorType, predicate.options, - std::move(left), std::move(right)); -} - -// Identify expressions of the form [SELF valueForKeyPath:] -bool is_self_value_for_key_path_function_expression(NSExpression *expression) -{ - if (expression.expressionType != NSFunctionExpressionType) - return false; - - if (expression.operand.expressionType != NSEvaluatedObjectExpressionType) - return false; - - return [expression.function isEqualToString:@"valueForKeyPath:"]; -} - -// -[NSPredicate predicateWithSubtitutionVariables:] results in function expressions of the form [SELF valueForKeyPath:] -// that apply_predicate cannot handle. Replace such expressions with equivalent NSKeyPathExpressionType expressions. -NSExpression *simplify_self_value_for_key_path_function_expression(NSExpression *expression) { - if (is_self_value_for_key_path_function_expression(expression)) { - if (NSString *keyPath = [expression.arguments.firstObject keyPath]) { - return [NSExpression expressionForKeyPath:keyPath]; - } - } - return expression; -} - -void QueryBuilder::apply_subquery_count_expression(RLMObjectSchema *objectSchema, - NSExpression *subqueryExpression, NSPredicateOperatorType operatorType, NSExpression *right) { - if (right.expressionType != NSConstantValueExpressionType || ![right.constantValue isKindOfClass:[NSNumber class]]) { - @throw RLMPredicateException(@"Invalid predicate expression", @"SUBQUERY(…).@count is only supported when compared with a constant number."); - } - int64_t value = [right.constantValue integerValue]; - - ColumnReference collectionColumn = column_reference_from_key_path(objectSchema, [subqueryExpression.collection keyPath], true); - RLMObjectSchema *collectionMemberObjectSchema = m_schema[collectionColumn.property().objectClassName]; - - // Eliminate references to the iteration variable in the subquery. - NSPredicate *subqueryPredicate = [subqueryExpression.predicate predicateWithSubstitutionVariables:@{ subqueryExpression.variable : [NSExpression expressionForEvaluatedObject] }]; - subqueryPredicate = transformPredicate(subqueryPredicate, simplify_self_value_for_key_path_function_expression); - - Query subquery = RLMPredicateToQuery(subqueryPredicate, collectionMemberObjectSchema, m_schema, m_group); - add_numeric_constraint(RLMPropertyTypeInt, operatorType, - collectionColumn.resolve(std::move(subquery)).count(), value); -} - -void QueryBuilder::apply_function_subquery_expression(RLMObjectSchema *objectSchema, NSExpression *functionExpression, - NSPredicateOperatorType operatorType, NSExpression *right) { - if (![functionExpression.function isEqualToString:@"valueForKeyPath:"] || functionExpression.arguments.count != 1) { - @throw RLMPredicateException(@"Invalid predicate", @"The '%@' function is not supported on the result of a SUBQUERY.", functionExpression.function); - } - - NSExpression *keyPathExpression = functionExpression.arguments.firstObject; - if ([keyPathExpression.keyPath isEqualToString:@"@count"]) { - apply_subquery_count_expression(objectSchema, functionExpression.operand, operatorType, right); - } else { - @throw RLMPredicateException(@"Invalid predicate", @"SUBQUERY is only supported when immediately followed by .@count that is compared with a constant number."); - } -} - -void QueryBuilder::apply_function_expression(RLMObjectSchema *objectSchema, NSExpression *functionExpression, - NSPredicateOperatorType operatorType, NSExpression *right) { - if (functionExpression.operand.expressionType == NSSubqueryExpressionType) { - apply_function_subquery_expression(objectSchema, functionExpression, operatorType, right); - } else { - @throw RLMPredicateException(@"Invalid predicate", @"The '%@' function is not supported.", functionExpression.function); - } -} - - -void QueryBuilder::apply_predicate(NSPredicate *predicate, RLMObjectSchema *objectSchema) -{ - // Compound predicates. - if ([predicate isMemberOfClass:[NSCompoundPredicate class]]) { - NSCompoundPredicate *comp = (NSCompoundPredicate *)predicate; - - switch ([comp compoundPredicateType]) { - case NSAndPredicateType: - if (comp.subpredicates.count) { - // Add all of the subpredicates. - m_query.group(); - for (NSPredicate *subp in comp.subpredicates) { - apply_predicate(subp, objectSchema); - } - m_query.end_group(); - } else { - // NSCompoundPredicate's documentation states that an AND predicate with no subpredicates evaluates to TRUE. - m_query.and_query(std::unique_ptr(new TrueExpression)); - } - break; - - case NSOrPredicateType: { - // Add all of the subpredicates with ors inbetween. - process_or_group(m_query, comp.subpredicates, [&](__unsafe_unretained NSPredicate *const subp) { - apply_predicate(subp, objectSchema); - }); - break; - } - - case NSNotPredicateType: - // Add the negated subpredicate - m_query.Not(); - apply_predicate(comp.subpredicates.firstObject, objectSchema); - break; - - default: - @throw RLMPredicateException(@"Invalid compound predicate type", - @"Only support AND, OR and NOT predicate types"); - } - } - else if ([predicate isMemberOfClass:[NSComparisonPredicate class]]) { - NSComparisonPredicate *compp = (NSComparisonPredicate *)predicate; - - // check modifier - RLMPrecondition(compp.comparisonPredicateModifier != NSAllPredicateModifier, - @"Invalid predicate", @"ALL modifier not supported"); - - NSExpressionType exp1Type = compp.leftExpression.expressionType; - NSExpressionType exp2Type = compp.rightExpression.expressionType; - - if (compp.comparisonPredicateModifier == NSAnyPredicateModifier) { - // for ANY queries - RLMPrecondition(exp1Type == NSKeyPathExpressionType && exp2Type == NSConstantValueExpressionType, - @"Invalid predicate", - @"Predicate with ANY modifier must compare a KeyPath with RLMArray with a value"); - } - - if (compp.predicateOperatorType == NSBetweenPredicateOperatorType || compp.predicateOperatorType == NSInPredicateOperatorType) { - // Inserting an array via %@ gives NSConstantValueExpressionType, but including it directly gives NSAggregateExpressionType - if (exp1Type == NSKeyPathExpressionType && (exp2Type == NSAggregateExpressionType || exp2Type == NSConstantValueExpressionType)) { - // "key.path IN %@", "key.path IN {…}", "key.path BETWEEN %@", or "key.path BETWEEN {…}". - exp2Type = NSConstantValueExpressionType; - } - else if (compp.predicateOperatorType == NSInPredicateOperatorType && exp1Type == NSConstantValueExpressionType && exp2Type == NSKeyPathExpressionType) { - // "%@ IN key.path" is equivalent to "ANY key.path IN %@". Rewrite the former into the latter. - compp = [NSComparisonPredicate predicateWithLeftExpression:compp.rightExpression rightExpression:compp.leftExpression - modifier:NSAnyPredicateModifier type:NSEqualToPredicateOperatorType options:0]; - exp1Type = NSKeyPathExpressionType; - exp2Type = NSConstantValueExpressionType; - } - else { - if (compp.predicateOperatorType == NSBetweenPredicateOperatorType) { - @throw RLMPredicateException(@"Invalid predicate", - @"Predicate with BETWEEN operator must compare a KeyPath with an aggregate with two values"); - } - else if (compp.predicateOperatorType == NSInPredicateOperatorType) { - @throw RLMPredicateException(@"Invalid predicate", - @"Predicate with IN operator must compare a KeyPath with an aggregate"); - } - } - } - - if (exp1Type == NSKeyPathExpressionType && exp2Type == NSKeyPathExpressionType) { - // both expression are KeyPaths - apply_column_expression(objectSchema, compp.leftExpression.keyPath, compp.rightExpression.keyPath, compp); - } - else if (exp1Type == NSKeyPathExpressionType && exp2Type == NSConstantValueExpressionType) { - // comparing keypath to value - apply_value_expression(objectSchema, compp.leftExpression.keyPath, compp.rightExpression.constantValue, compp); - } - else if (exp1Type == NSConstantValueExpressionType && exp2Type == NSKeyPathExpressionType) { - // comparing value to keypath - apply_value_expression(objectSchema, compp.rightExpression.keyPath, compp.leftExpression.constantValue, compp); - } - else if (exp1Type == NSFunctionExpressionType) { - apply_function_expression(objectSchema, compp.leftExpression, compp.predicateOperatorType, compp.rightExpression); - } - else if (exp1Type == NSSubqueryExpressionType) { - // The subquery expressions that we support are handled by the NSFunctionExpressionType case above. - @throw RLMPredicateException(@"Invalid predicate expression", @"SUBQUERY is only supported when immediately followed by .@count."); - } - else { - @throw RLMPredicateException(@"Invalid predicate expressions", - @"Predicate expressions must compare a keypath and another keypath or a constant value"); - } - } - else if ([predicate isEqual:[NSPredicate predicateWithValue:YES]]) { - m_query.and_query(std::unique_ptr(new TrueExpression)); - } else if ([predicate isEqual:[NSPredicate predicateWithValue:NO]]) { - m_query.and_query(std::unique_ptr(new FalseExpression)); - } - else { - // invalid predicate type - @throw RLMPredicateException(@"Invalid predicate", - @"Only support compound, comparison, and constant predicates"); - } -} - -size_t RLMValidatedColumnForSort(Table& table, NSString *propName) { - RLMPrecondition([propName rangeOfString:@"."].location == NSNotFound, - @"Invalid sort property", @"Cannot sort on '%@': sorting on key paths is not supported.", propName); - size_t column = table.get_column_index(propName.UTF8String); - RLMPrecondition(column != npos, @"Invalid sort property", - @"Cannot sort on property '%@' on object of type '%s': property not found.", - propName, ObjectStore::object_type_for_table_name(table.get_name()).data()); - - switch (auto type = static_cast(table.get_column_type(column))) { - case RLMPropertyTypeBool: - case RLMPropertyTypeDate: - case RLMPropertyTypeDouble: - case RLMPropertyTypeFloat: - case RLMPropertyTypeInt: - case RLMPropertyTypeString: - break; - - default: - @throw RLMPredicateException(@"Invalid sort property type", - @"Cannot sort on property '%@' on object of type '%s': sorting is only supported on bool, date, double, float, integer, and string properties, but property is of type %@.", - propName, ObjectStore::object_type_for_table_name(table.get_name()).data(), - RLMTypeToString(type)); - } - return column; -} - -} // namespace - -realm::Query RLMPredicateToQuery(NSPredicate *predicate, RLMObjectSchema *objectSchema, - RLMSchema *schema, Group &group) -{ - auto query = get_table(group, objectSchema).where(); - - // passing a nil predicate is a no-op - if (!predicate) { - return query; - } - - @autoreleasepool { - QueryBuilder(query, group, schema).apply_predicate(predicate, objectSchema); - } - - // Test the constructed query in core - std::string validateMessage = query.validate(); - RLMPrecondition(validateMessage.empty(), @"Invalid query", @"%.*s", - (int)validateMessage.size(), validateMessage.c_str()); - return query; -} - -realm::SortDescriptor RLMSortDescriptorFromDescriptors(realm::Table& table, NSArray *descriptors) { - std::vector> columnIndices; - std::vector ascending; - columnIndices.reserve(descriptors.count); - ascending.reserve(descriptors.count); - - for (RLMSortDescriptor *descriptor in descriptors) { - columnIndices.push_back({RLMValidatedColumnForSort(table, descriptor.property)}); - ascending.push_back(descriptor.ascending); - } - - return {table, std::move(columnIndices), std::move(ascending)}; -} diff --git a/Example/Pods/Realm/Realm/RLMRealm.mm b/Example/Pods/Realm/Realm/RLMRealm.mm deleted file mode 100644 index 4f440fe..0000000 --- a/Example/Pods/Realm/Realm/RLMRealm.mm +++ /dev/null @@ -1,737 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMRealm_Private.hpp" - -#import "RLMAnalytics.hpp" -#import "RLMArray_Private.hpp" -#import "RLMRealmConfiguration_Private.hpp" -#import "RLMMigration_Private.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMProperty_Private.h" -#import "RLMObjectStore.h" -#import "RLMObject_Private.h" -#import "RLMObject_Private.hpp" -#import "RLMObservation.hpp" -#import "RLMProperty.h" -#import "RLMQueryUtil.hpp" -#import "RLMRealmUtil.hpp" -#import "RLMSchema_Private.hpp" -#import "RLMSyncManager_Private.h" -#import "RLMUpdateChecker.hpp" -#import "RLMUtil.hpp" - -#include "impl/realm_coordinator.hpp" -#include "object_store.hpp" -#include "schema.hpp" -#include "shared_realm.hpp" - -#include -#include -#include - -using namespace realm; -using util::File; - -@interface RLMRealmNotificationToken : RLMNotificationToken -@property (nonatomic, strong) RLMRealm *realm; -@property (nonatomic, copy) RLMNotificationBlock block; -@end - -@interface RLMRealm () -@property (nonatomic, strong) NSHashTable *notificationHandlers; -- (void)sendNotifications:(RLMNotification)notification; -@end - -void RLMDisableSyncToDisk() { - realm::disable_sync_to_disk(); -} - -@implementation RLMRealmNotificationToken -- (void)stop { - [_realm verifyThread]; - [_realm.notificationHandlers removeObject:self]; - _realm = nil; - _block = nil; -} - -- (void)suppressNextNotification { - // Temporarily replace the block with one which restores the old block - // rather than producing a notification. - - // This briefly creates a retain cycle but it's fine because the block will - // be synchronously called shortly after this method is called. Unlike with - // collection notifications, this does not have to go through the object - // store or do fancy things to handle transaction coalescing because it's - // called synchronously by the obj-c code and not by the object store. - auto notificationBlock = _block; - _block = ^(RLMNotification, RLMRealm *) { - _block = notificationBlock; - }; -} - -- (void)dealloc { - if (_realm || _block) { - NSLog(@"RLMNotificationToken released without unregistering a notification. You must hold " - @"on to the RLMNotificationToken returned from addNotificationBlock and call " - @"-[RLMNotificationToken stop] when you no longer wish to receive RLMRealm notifications."); - } -} -@end - -static bool shouldForciblyDisableEncryption() { - static bool disableEncryption = getenv("REALM_DISABLE_ENCRYPTION"); - return disableEncryption; -} - -NSData *RLMRealmValidatedEncryptionKey(NSData *key) { - if (shouldForciblyDisableEncryption()) { - return nil; - } - - if (key) { - if (key.length != 64) { - @throw RLMException(@"Encryption key must be exactly 64 bytes long"); - } -#if TARGET_OS_WATCH - @throw RLMException(@"Cannot open an encrypted Realm on watchOS."); -#endif - } - - return key; -} - -@implementation RLMRealm { - NSHashTable *_collectionEnumerators; - bool _sendingNotifications; -} - -+ (BOOL)isCoreDebug { - return realm::Version::has_feature(realm::feature_Debug); -} - -+ (void)initialize { - static bool initialized; - if (initialized) { - return; - } - initialized = true; - - RLMCheckForUpdates(); - RLMSendAnalytics(); -} - -- (BOOL)isEmpty { - return realm::ObjectStore::is_empty(self.group); -} - -- (void)verifyThread { - _realm->verify_thread(); -} - -- (BOOL)inWriteTransaction { - return _realm->is_in_transaction(); -} - -- (realm::Group &)group { - return _realm->read_group(); -} - -- (BOOL)autorefresh { - return _realm->auto_refresh(); -} - -- (void)setAutorefresh:(BOOL)autorefresh { - _realm->set_auto_refresh(autorefresh); -} - -+ (instancetype)defaultRealm { - return [RLMRealm realmWithConfiguration:[RLMRealmConfiguration rawDefaultConfiguration] error:nil]; -} - -+ (instancetype)realmWithURL:(NSURL *)fileURL { - RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration]; - configuration.fileURL = fileURL; - return [RLMRealm realmWithConfiguration:configuration error:nil]; -} -// ARC tries to eliminate calls to autorelease when the value is then immediately -// returned, but this results in significantly different semantics between debug -// and release builds for RLMRealm, so force it to always autorelease. -static id RLMAutorelease(id value) { - // +1 __bridge_retained, -1 CFAutorelease - return value ? (__bridge id)CFAutorelease((__bridge_retained CFTypeRef)value) : nil; -} - -static void RLMRealmSetSchemaAndAlign(RLMRealm *realm, RLMSchema *targetSchema) { - realm.schema = targetSchema; - realm->_info = RLMSchemaInfo(realm, targetSchema, realm->_realm->schema()); -} - -+ (instancetype)realmWithSharedRealm:(SharedRealm)sharedRealm schema:(RLMSchema *)schema { - RLMRealm *realm = [RLMRealm new]; - realm->_realm = sharedRealm; - realm->_dynamic = YES; - RLMRealmSetSchemaAndAlign(realm, schema); - return RLMAutorelease(realm); -} - -REALM_NOINLINE void RLMRealmTranslateException(NSError **error) { - try { - throw; - } - catch (RealmFileException const& ex) { - switch (ex.kind()) { - case RealmFileException::Kind::PermissionDenied: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFilePermissionDenied, ex), error); - break; - case RealmFileException::Kind::IncompatibleLockFile: { - NSString *err = @"Realm file is currently open in another process " - "which cannot share access with this process. All " - "processes sharing a single file must be the same " - "architecture. For sharing files between the Realm " - "Browser and an iOS simulator, this means that you " - "must use a 64-bit simulator."; - RLMSetErrorOrThrow(RLMMakeError(RLMErrorIncompatibleLockFile, - File::PermissionDenied(err.UTF8String, ex.path())), error); - break; - } - case RealmFileException::Kind::NotFound: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileNotFound, ex), error); - break; - case RealmFileException::Kind::Exists: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileExists, ex), error); - break; - case RealmFileException::Kind::BadHistoryError: { - NSString *err = @"Realm file's history format is incompatible with the " - "settings in the configuration object being used to open " - "the Realm. Note that Realms configured for sync cannot be " - "opened as non-synced Realms, and vice versa. Otherwise, the " - "file may be corrupt."; - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileAccess, - File::AccessError(err.UTF8String, ex.path())), error); - break; - } - case RealmFileException::Kind::AccessError: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileAccess, ex), error); - break; - case RealmFileException::Kind::FormatUpgradeRequired: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileFormatUpgradeRequired, ex), error); - break; - default: - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, ex), error); - break; - } - } - catch (AddressSpaceExhausted const &ex) { - RLMSetErrorOrThrow(RLMMakeError(RLMErrorAddressSpaceExhausted, ex), error); - } - catch (SchemaMismatchException const& ex) { - RLMSetErrorOrThrow(RLMMakeError(RLMErrorSchemaMismatch, ex), error); - } - catch (std::system_error const& ex) { - RLMSetErrorOrThrow(RLMMakeError(ex), error); - } - catch (const std::exception &exp) { - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), error); - } -} - -+ (instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error { - bool dynamic = configuration.dynamic; - bool readOnly = configuration.readOnly; - - { - Realm::Config& config = configuration.config; - - // try to reuse existing realm first - if (config.cache || dynamic) { - if (RLMRealm *realm = RLMGetThreadLocalCachedRealmForPath(config.path)) { - auto const& old_config = realm->_realm->config(); - if (old_config.read_only() != config.read_only()) { - @throw RLMException(@"Realm at path '%s' already opened with different read permissions", config.path.c_str()); - } - if (old_config.in_memory != config.in_memory) { - @throw RLMException(@"Realm at path '%s' already opened with different inMemory settings", config.path.c_str()); - } - if (realm->_dynamic != dynamic) { - @throw RLMException(@"Realm at path '%s' already opened with different dynamic settings", config.path.c_str()); - } - if (old_config.encryption_key != config.encryption_key) { - @throw RLMException(@"Realm at path '%s' already opened with different encryption key", config.path.c_str()); - } - return RLMAutorelease(realm); - } - } - } - - configuration = [configuration copy]; - Realm::Config& config = configuration.config; - - RLMRealm *realm = [RLMRealm new]; - realm->_dynamic = dynamic; - - // protects the realm cache and accessors cache - static std::mutex initLock; - std::lock_guard lock(initLock); - - try { - realm->_realm = Realm::get_shared_realm(config); - } - catch (...) { - RLMRealmTranslateException(error); - return nil; - } - - // if we have a cached realm on another thread, copy without a transaction - if (RLMRealm *cachedRealm = RLMGetAnyCachedRealmForPath(config.path)) { - RLMRealmSetSchemaAndAlign(realm, cachedRealm.schema); - } - else if (dynamic) { - RLMRealmSetSchemaAndAlign(realm, [RLMSchema dynamicSchemaFromObjectStoreSchema:realm->_realm->schema()]); - } - else { - // set/align schema or perform migration if needed - RLMSchema *schema = configuration.customSchema ?: RLMSchema.sharedSchema; - - Realm::MigrationFunction migrationFunction; - auto migrationBlock = configuration.migrationBlock; - if (migrationBlock && configuration.schemaVersion > 0) { - migrationFunction = [=](SharedRealm old_realm, SharedRealm realm, Schema& mutableSchema) { - RLMSchema *oldSchema = [RLMSchema dynamicSchemaFromObjectStoreSchema:old_realm->schema()]; - RLMRealm *oldRealm = [RLMRealm realmWithSharedRealm:old_realm schema:oldSchema]; - - // The destination RLMRealm can't just use the schema from the - // SharedRealm because it doesn't have information about whether or - // not a class was defined in Swift, which effects how new objects - // are created - RLMRealm *newRealm = [RLMRealm realmWithSharedRealm:realm schema:schema.copy]; - - [[[RLMMigration alloc] initWithRealm:newRealm oldRealm:oldRealm schema:mutableSchema] execute:migrationBlock]; - - oldRealm->_realm = nullptr; - newRealm->_realm = nullptr; - }; - } - - try { - realm->_realm->update_schema(schema.objectStoreCopy, config.schema_version, - std::move(migrationFunction)); - } - catch (...) { - RLMRealmTranslateException(error); - return nil; - } - - RLMRealmSetSchemaAndAlign(realm, schema); - RLMRealmCreateAccessors(realm.schema); - - if (!readOnly) { - // initializing the schema started a read transaction, so end it - [realm invalidate]; - } - } - - if (config.cache) { - RLMCacheRealm(config.path, realm); - } - - if (!readOnly) { - realm->_realm->m_binding_context = RLMCreateBindingContext(realm); - } - - return RLMAutorelease(realm); -} - -+ (void)resetRealmState { - RLMClearRealmCache(); - realm::_impl::RealmCoordinator::clear_cache(); - [RLMRealmConfiguration resetRealmConfigurationState]; -} - -- (void)verifyNotificationsAreSupported { - [self verifyThread]; - if (_realm->config().read_only()) { - @throw RLMException(@"Read-only Realms do not change and do not have change notifications"); - } - if (!_realm->can_deliver_notifications()) { - @throw RLMException(@"Can only add notification blocks from within runloops."); - } -} - -- (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block { - if (!block) { - @throw RLMException(@"The notification block should not be nil"); - } - [self verifyNotificationsAreSupported]; - - _realm->read_group(); - - if (!_notificationHandlers) { - _notificationHandlers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]; - } - - RLMRealmNotificationToken *token = [[RLMRealmNotificationToken alloc] init]; - token.realm = self; - token.block = block; - [_notificationHandlers addObject:token]; - return token; -} - -- (void)sendNotifications:(RLMNotification)notification { - NSAssert(!_realm->config().read_only(), @"Read-only realms do not have notifications"); - if (_sendingNotifications) { - return; - } - NSUInteger count = _notificationHandlers.count; - if (count == 0) { - return; - } - - _sendingNotifications = true; - auto cleanup = realm::util::make_scope_exit([&]() noexcept { - _sendingNotifications = false; - }); - - // call this realm's notification blocks - if (count == 1) { - if (auto block = [_notificationHandlers.anyObject block]) { - block(notification, self); - } - } - else { - for (RLMRealmNotificationToken *token in _notificationHandlers.allObjects) { - if (auto block = token.block) { - block(notification, self); - } - } - } -} - -- (RLMRealmConfiguration *)configuration { - RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init]; - configuration.config = _realm->config(); - configuration.dynamic = _dynamic; - configuration.customSchema = _schema; - return configuration; -} - -- (void)beginWriteTransaction { - try { - _realm->begin_transaction(); - } - catch (std::exception &ex) { - @throw RLMException(ex); - } -} - -- (void)commitWriteTransaction { - [self commitWriteTransaction:nil]; -} - -- (BOOL)commitWriteTransaction:(NSError **)outError { - try { - _realm->commit_transaction(); - return YES; - } - catch (...) { - RLMRealmTranslateException(outError); - return NO; - } -} - -- (BOOL)commitWriteTransactionWithoutNotifying:(NSArray *)tokens error:(NSError **)error { - for (RLMNotificationToken *token in tokens) { - if (token.realm != self) { - @throw RLMException(@"Incorrect Realm: only notifications for the Realm being modified can be skipped."); - } - [token suppressNextNotification]; - } - - try { - _realm->commit_transaction(); - return YES; - } - catch (...) { - RLMRealmTranslateException(error); - return NO; - } -} - -- (void)transactionWithBlock:(void(^)(void))block { - [self transactionWithBlock:block error:nil]; -} - -- (BOOL)transactionWithBlock:(void(^)(void))block error:(NSError **)outError { - [self beginWriteTransaction]; - block(); - if (_realm->is_in_transaction()) { - return [self commitWriteTransaction:outError]; - } - return YES; -} - -- (void)cancelWriteTransaction { - try { - _realm->cancel_transaction(); - } - catch (std::exception &ex) { - @throw RLMException(ex); - } -} - -- (void)invalidate { - if (_realm->is_in_transaction()) { - NSLog(@"WARNING: An RLMRealm instance was invalidated during a write " - "transaction and all pending changes have been rolled back."); - } - - [self detachAllEnumerators]; - - for (auto& objectInfo : _info) { - for (RLMObservationInfo *info : objectInfo.second.observedObjects) { - info->willChange(RLMInvalidatedKey); - } - } - - _realm->invalidate(); - - for (auto& objectInfo : _info) { - for (RLMObservationInfo *info : objectInfo.second.observedObjects) { - info->didChange(RLMInvalidatedKey); - } - objectInfo.second.releaseTable(); - } -} - -/** - Replaces all string columns in this Realm with a string enumeration column and compacts the - database file. - - Cannot be called from a write transaction. - - Compaction will not occur if other `RLMRealm` instances exist. - - While compaction is in progress, attempts by other threads or processes to open the database will - wait. - - Be warned that resource requirements for compaction is proportional to the amount of live data in - the database. - - Compaction works by writing the database contents to a temporary database file and then replacing - the database with the temporary one. The name of the temporary file is formed by appending - `.tmp_compaction_space` to the name of the database. - - @return YES if the compaction succeeded. - */ -- (BOOL)compact { - // compact() automatically ends the read transaction, but we need to clean - // up cached state and send invalidated notifications when that happens, so - // explicitly end it first unless we're in a write transaction (in which - // case compact() will throw an exception) - if (!_realm->is_in_transaction()) { - [self invalidate]; - } - - try { - return _realm->compact(); - } - catch (std::exception const& ex) { - @throw RLMException(ex); - } -} - -- (void)dealloc { - if (_realm) { - if (_realm->is_in_transaction()) { - [self cancelWriteTransaction]; - NSLog(@"WARNING: An RLMRealm instance was deallocated during a write transaction and all " - "pending changes have been rolled back. Make sure to retain a reference to the " - "RLMRealm for the duration of the write transaction."); - } - } -} - -- (BOOL)refresh { - return _realm->refresh(); -} - -- (void)addObject:(__unsafe_unretained RLMObject *const)object { - RLMAddObjectToRealm(object, self, false); -} - -- (void)addObjects:(id)array { - for (RLMObject *obj in array) { - if (![obj isKindOfClass:[RLMObject class]]) { - @throw RLMException(@"Cannot insert objects of type %@ with addObjects:. Only RLMObjects are supported.", - NSStringFromClass(obj.class)); - } - [self addObject:obj]; - } -} - -- (void)addOrUpdateObject:(RLMObject *)object { - // verify primary key - if (!object.objectSchema.primaryKeyProperty) { - @throw RLMException(@"'%@' does not have a primary key and can not be updated", object.objectSchema.className); - } - - RLMAddObjectToRealm(object, self, true); -} - -- (void)addOrUpdateObjectsFromArray:(id)array { - for (RLMObject *obj in array) { - [self addOrUpdateObject:obj]; - } -} - -- (void)deleteObject:(RLMObject *)object { - RLMDeleteObjectFromRealm(object, self); -} - -- (void)deleteObjects:(id)array { - if ([array respondsToSelector:@selector(realm)] && [array respondsToSelector:@selector(deleteObjectsFromRealm)]) { - if (self != (RLMRealm *)[array realm]) { - @throw RLMException(@"Can only delete objects from the Realm they belong to."); - } - [array deleteObjectsFromRealm]; - } - else if ([array conformsToProtocol:@protocol(NSFastEnumeration)]) { - for (id obj in array) { - if ([obj isKindOfClass:RLMObjectBase.class]) { - RLMDeleteObjectFromRealm(obj, self); - } - } - } - else { - @throw RLMException(@"Invalid array type - container must be an RLMArray, RLMArray, or NSArray of RLMObjects"); - } -} - -- (void)deleteAllObjects { - RLMDeleteAllObjectsFromRealm(self); -} - -- (RLMResults *)allObjects:(NSString *)objectClassName { - return RLMGetObjects(self, objectClassName, nil); -} - -- (RLMResults *)objects:(NSString *)objectClassName where:(NSString *)predicateFormat, ... { - va_list args; - va_start(args, predicateFormat); - RLMResults *results = [self objects:objectClassName where:predicateFormat args:args]; - va_end(args); - return results; -} - -- (RLMResults *)objects:(NSString *)objectClassName where:(NSString *)predicateFormat args:(va_list)args { - return [self objects:objectClassName withPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]]; -} - -- (RLMResults *)objects:(NSString *)objectClassName withPredicate:(NSPredicate *)predicate { - return RLMGetObjects(self, objectClassName, predicate); -} - -- (RLMObject *)objectWithClassName:(NSString *)className forPrimaryKey:(id)primaryKey { - return RLMGetObject(self, className, primaryKey); -} - -+ (uint64_t)schemaVersionAtURL:(NSURL *)fileURL encryptionKey:(NSData *)key error:(NSError **)error { - try { - RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init]; - config.fileURL = fileURL; - config.encryptionKey = RLMRealmValidatedEncryptionKey(key); - - uint64_t version = Realm::get_schema_version(config.config); - if (version == realm::ObjectStore::NotVersioned) { - RLMSetErrorOrThrow([NSError errorWithDomain:RLMErrorDomain code:RLMErrorFail userInfo:@{NSLocalizedDescriptionKey:@"Cannot open an uninitialized realm in read-only mode"}], error); - } - return version; - } - catch (std::exception &exp) { - RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), error); - return RLMNotVersioned; - } -} - -+ (nullable NSError *)migrateRealm:(RLMRealmConfiguration *)configuration { - // Preserves backwards compatibility - NSError *error; - [self performMigrationForConfiguration:configuration error:&error]; - return error; -} - -+ (BOOL)performMigrationForConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error { - if (RLMGetAnyCachedRealmForPath(configuration.config.path)) { - @throw RLMException(@"Cannot migrate Realms that are already open."); - } - - NSError *localError; // Prevents autorelease - BOOL success; - @autoreleasepool { - success = [RLMRealm realmWithConfiguration:configuration error:&localError] != nil; - } - if (!success && error) { - *error = localError; // Must set outside pool otherwise will free anyway - } - return success; -} - -- (RLMObject *)createObject:(NSString *)className withValue:(id)value { - return (RLMObject *)RLMCreateObjectInRealmWithValue(self, className, value, false); -} - -- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(NSData *)key error:(NSError **)error { - key = RLMRealmValidatedEncryptionKey(key); - NSString *path = fileURL.path; - - try { - _realm->write_copy(path.UTF8String, {static_cast(key.bytes), key.length}); - return YES; - } - catch (...) { - __autoreleasing NSError *dummyError; - if (!error) { - error = &dummyError; - } - RLMRealmTranslateException(error); - return NO; - } - - return NO; -} - -- (void)registerEnumerator:(RLMFastEnumerator *)enumerator { - if (!_collectionEnumerators) { - _collectionEnumerators = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory]; - } - [_collectionEnumerators addObject:enumerator]; - -} - -- (void)unregisterEnumerator:(RLMFastEnumerator *)enumerator { - [_collectionEnumerators removeObject:enumerator]; -} - -- (void)detachAllEnumerators { - for (RLMFastEnumerator *enumerator in _collectionEnumerators) { - [enumerator detach]; - } - _collectionEnumerators = nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm b/Example/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm deleted file mode 100644 index 528d732..0000000 --- a/Example/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm +++ /dev/null @@ -1,64 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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+Sync.h" - -#import "RLMRealmConfiguration_Private.hpp" -#import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncUser_Private.hpp" -#import "RLMSyncManager_Private.h" -#import "RLMSyncUtil_Private.hpp" -#import "RLMUtil.hpp" - -#import "sync/sync_config.hpp" -#import "sync/sync_manager.hpp" - -@implementation RLMRealmConfiguration (Sync) - -#pragma mark - API - -- (void)setSyncConfiguration:(RLMSyncConfiguration *)syncConfiguration { - RLMSyncUser *user = syncConfiguration.user; - if (user.state == RLMSyncUserStateError) { - @throw RLMException(@"Cannot set a sync configuration which has an errored-out user."); - } - - NSURL *realmURL = syncConfiguration.realmURL; - // Ensure sync manager is initialized, if it hasn't already been. - [RLMSyncManager sharedManager]; - NSAssert(user.identity, @"Cannot call this method on a user that doesn't have an identity."); - if (syncConfiguration.customFileURL) { - self.config.path = syncConfiguration.customFileURL.path.UTF8String; - } else { - self.config.path = SyncManager::shared().path_for_realm([user.identity UTF8String], - [realmURL.absoluteString UTF8String]); - } - self.config.in_memory = false; - self.config.sync_config = std::make_shared([syncConfiguration rawConfiguration]); - self.config.schema_mode = realm::SchemaMode::Additive; -} - -- (RLMSyncConfiguration *)syncConfiguration { - if (!self.config.sync_config) { - return nil; - } - realm::SyncConfig& sync_config = *self.config.sync_config; - return [[RLMSyncConfiguration alloc] initWithRawConfig:sync_config]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMRealmConfiguration.mm b/Example/Pods/Realm/Realm/RLMRealmConfiguration.mm deleted file mode 100644 index b6ea49e..0000000 --- a/Example/Pods/Realm/Realm/RLMRealmConfiguration.mm +++ /dev/null @@ -1,266 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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" - -static NSString *const c_RLMRealmConfigurationProperties[] = { - @"fileURL", - @"inMemoryIdentifier", - @"encryptionKey", - @"readOnly", - @"schemaVersion", - @"migrationBlock", - @"deleteRealmIfMigrationNeeded", - @"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 { - @synchronized(c_defaultRealmFileName) { - if (!s_defaultConfiguration) { - s_defaultConfiguration = [[RLMRealmConfiguration alloc] init]; - } - } - return s_defaultConfiguration; -} - -+ (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; - } - - return self; -} - -- (instancetype)copyWithZone:(NSZone *)zone { - RLMRealmConfiguration *configuration = [[[self class] allocWithZone:zone] init]; - configuration->_config = _config; - configuration->_dynamic = _dynamic; - configuration->_migrationBlock = _migrationBlock; - 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(key.bytes); - _config.encryption_key.assign(bytes, bytes + key.length); - } - else { - _config.encryption_key.clear(); - } -} - -- (BOOL)readOnly { - return _config.read_only(); -} - -- (void)setReadOnly:(BOOL)readOnly { - if (readOnly) { - if (self.deleteRealmIfMigrationNeeded) { - @throw RLMException(@"Cannot set `readOnly` when `deleteRealmIfMigrationNeeded` is set."); - } - _config.schema_mode = realm::SchemaMode::ReadOnly; - } - 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; - _config.cache = !dynamic; -} - -- (bool)cache { - return _config.cache; -} - -- (void)setCache:(bool)cache { - _config.cache = cache; -} - -- (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; -} - -@end - diff --git a/Example/Pods/Realm/Realm/RLMRealmUtil.mm b/Example/Pods/Realm/Realm/RLMRealmUtil.mm deleted file mode 100644 index 41c0b51..0000000 --- a/Example/Pods/Realm/Realm/RLMRealmUtil.mm +++ /dev/null @@ -1,144 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMRealmUtil.hpp" - -#import "RLMObjectSchema_Private.hpp" -#import "RLMObservation.hpp" -#import "RLMRealm_Private.hpp" -#import "RLMUtil.hpp" - -#import -#import - -#import "binding_context.hpp" - -#import -#import -#import -#import -#import -#import - -// Global realm state -static std::mutex s_realmCacheMutex; -static std::map s_realmsPerPath; - -void RLMCacheRealm(std::string const& path, RLMRealm *realm) { - std::lock_guard lock(s_realmCacheMutex); - NSMapTable *realms = s_realmsPerPath[path]; - if (!realms) { - s_realmsPerPath[path] = realms = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsObjectPersonality - valueOptions:NSPointerFunctionsWeakMemory]; - } - [realms setObject:realm forKey:@(pthread_mach_thread_np(pthread_self()))]; -} - -RLMRealm *RLMGetAnyCachedRealmForPath(std::string const& path) { - std::lock_guard lock(s_realmCacheMutex); - return [s_realmsPerPath[path] objectEnumerator].nextObject; -} - -RLMRealm *RLMGetThreadLocalCachedRealmForPath(std::string const& path) { - mach_port_t threadID = pthread_mach_thread_np(pthread_self()); - std::lock_guard lock(s_realmCacheMutex); - return [s_realmsPerPath[path] objectForKey:@(threadID)]; -} - -void RLMClearRealmCache() { - std::lock_guard lock(s_realmCacheMutex); - s_realmsPerPath.clear(); -} - -namespace { -class RLMNotificationHelper : public realm::BindingContext { -public: - RLMNotificationHelper(RLMRealm *realm) : _realm(realm) { } - - bool can_deliver_notifications() const noexcept override { - // The main thread may not be in a run loop yet if we're called from - // something like `applicationDidFinishLaunching:`, but it presumably will - // be in the future - if ([NSThread isMainThread]) { - return true; - } - // Current mode indicates why the current callout from the runloop was made, - // and is null if a runloop callout isn't currently being processed - if (auto mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent())) { - CFRelease(mode); - return true; - } - return false; - } - - void changes_available() override { - @autoreleasepool { - auto realm = _realm; - if (realm && !realm.autorefresh) { - [realm sendNotifications:RLMRealmRefreshRequiredNotification]; - } - } - } - - std::vector get_observed_rows() override { - @autoreleasepool { - if (auto realm = _realm) { - [realm detachAllEnumerators]; - return RLMGetObservedRows(realm->_info); - } - return {}; - } - } - - void will_change(std::vector const& observed, std::vector const& invalidated) override { - @autoreleasepool { - RLMWillChange(observed, invalidated); - } - } - - void did_change(std::vector const& observed, std::vector const& invalidated, bool version_changed) override { - try { - @autoreleasepool { - RLMDidChange(observed, invalidated); - if (version_changed) { - [_realm sendNotifications:RLMRealmDidChangeNotification]; - } - } - } - catch (...) { - // This can only be called during a write transaction if it was - // called due to the transaction beginning, so cancel it to ensure - // exceptions thrown here behave the same as exceptions thrown when - // actually beginning the write - if (_realm.inWriteTransaction) { - [_realm cancelWriteTransaction]; - } - throw; - } - } - -private: - // This is owned by the realm, so it needs to not retain the realm - __weak RLMRealm *const _realm; -}; -} // anonymous namespace - - -std::unique_ptr RLMCreateBindingContext(RLMRealm *realm) { - return std::unique_ptr(new RLMNotificationHelper(realm)); -} diff --git a/Example/Pods/Realm/Realm/RLMResults.mm b/Example/Pods/Realm/Realm/RLMResults.mm deleted file mode 100644 index 40420f7..0000000 --- a/Example/Pods/Realm/Realm/RLMResults.mm +++ /dev/null @@ -1,452 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMResults_Private.h" - -#import "RLMArray_Private.hpp" -#import "RLMCollection_Private.hpp" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObject_Private.hpp" -#import "RLMObservation.hpp" -#import "RLMProperty_Private.h" -#import "RLMQueryUtil.hpp" -#import "RLMRealm_Private.hpp" -#import "RLMSchema_Private.h" -#import "RLMUtil.hpp" - -#import "results.hpp" - -#import -#import -#import - -using namespace realm; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wincomplete-implementation" -@implementation RLMNotificationToken -@end -#pragma clang diagnostic pop - -// -// RLMResults implementation -// -@implementation RLMResults { - realm::Results _results; - RLMRealm *_realm; - RLMClassInfo *_info; -} - -- (instancetype)initPrivate { - self = [super init]; - return self; -} - -static void assertKeyPathIsNotNested(NSString *keyPath) { - if ([keyPath rangeOfString:@"."].location != NSNotFound) { - @throw RLMException(@"Nested key paths are not supported yet for KVC collection operators."); - } -} - -[[gnu::noinline]] -[[noreturn]] -static void throwError(NSString *aggregateMethod) { - try { - throw; - } - catch (realm::InvalidTransactionException const&) { - @throw RLMException(@"Cannot modify Results outside of a write transaction"); - } - catch (realm::IncorrectThreadException const&) { - @throw RLMException(@"Realm accessed from incorrect thread"); - } - catch (realm::Results::InvalidatedException const&) { - @throw RLMException(@"RLMResults has been invalidated"); - } - catch (realm::Results::DetatchedAccessorException const&) { - @throw RLMException(@"Object has been invalidated"); - } - catch (realm::Results::IncorrectTableException const& e) { - @throw RLMException(@"Object type '%s' does not match RLMResults type '%s'.", - e.actual.data(), e.expected.data()); - } - catch (realm::Results::OutOfBoundsIndexException const& e) { - @throw RLMException(@"Index %zu is out of bounds (must be less than %zu)", - e.requested, e.valid_count); - } - catch (realm::Results::UnsupportedColumnTypeException const& e) { - @throw RLMException(@"%@ is not supported for %@ property '%s'", - aggregateMethod, - RLMTypeToString((RLMPropertyType)e.column_type), - e.column_name.data()); - } -} - -template -static auto translateErrors(Function&& f, NSString *aggregateMethod=nil) { - try { - return f(); - } - catch (...) { - throwError(aggregateMethod); - } -} - -+ (instancetype)resultsWithObjectInfo:(RLMClassInfo&)info - results:(realm::Results)results { - RLMResults *ar = [[self alloc] initPrivate]; - ar->_results = std::move(results); - ar->_realm = info.realm; - ar->_info = &info; - return ar; -} - -+ (instancetype)emptyDetachedResults { - return [[self alloc] initPrivate]; -} - -static inline void RLMResultsValidateInWriteTransaction(__unsafe_unretained RLMResults *const ar) { - ar->_realm->_realm->verify_thread(); - ar->_realm->_realm->verify_in_write(); -} - -- (BOOL)isInvalidated { - return translateErrors([&] { return !_results.is_valid(); }); -} - -- (NSUInteger)count { - return translateErrors([&] { return _results.size(); }); -} - -- (NSString *)objectClassName { - return RLMStringDataToNSString(_results.get_object_type()); -} - -- (RLMClassInfo *)objectInfo { - return _info; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(__unused __unsafe_unretained id [])buffer - count:(NSUInteger)len { - if (!_info) { - return 0; - } - - __autoreleasing RLMFastEnumerator *enumerator; - if (state->state == 0) { - enumerator = [[RLMFastEnumerator alloc] initWithCollection:self objectSchema:*_info]; - state->extra[0] = (long)enumerator; - state->extra[1] = self.count; - } - else { - enumerator = (__bridge id)(void *)state->extra[0]; - } - - return [enumerator countByEnumeratingWithState:state count:len]; -} - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ... { - va_list args; - va_start(args, predicateFormat); - NSUInteger index = [self indexOfObjectWhere:predicateFormat args:args]; - va_end(args); - return index; -} - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args { - return [self indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:predicateFormat - arguments:args]]; -} - -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate { - if (_results.get_mode() == Results::Mode::Empty) { - return NSNotFound; - } - - Query query = translateErrors([&] { return _results.get_query(); }); - query.and_query(RLMPredicateToQuery(predicate, _info->rlmObjectSchema, _realm.schema, _realm.group)); - query.sync_view_if_needed(); - -#if REALM_VER_MAJOR >= 2 - size_t indexInTable; - if (const auto& sort = _results.get_sort()) { - // A sort order is specified so we need to return the first match given that ordering. - TableView table_view = query.find_all(); - table_view.sort(sort); - if (!table_view.size()) { - return NSNotFound; - } - indexInTable = table_view.get_source_ndx(0); - } else { - indexInTable = query.find(); - } - if (indexInTable == realm::not_found) { - return NSNotFound; - } - return RLMConvertNotFound(_results.index_of(indexInTable)); -#else - TableView table_view; - if (const auto& sort = _results.get_sort()) { - // A sort order is specified so we need to return the first match given that ordering. - table_view = query.find_all(); - table_view.sort(sort); - } else { - table_view = query.find_all(0, -1, 1); - } - if (!table_view.size()) { - return NSNotFound; - } - return _results.index_of(table_view.get_source_ndx(0)); -#endif -} - -- (id)objectAtIndex:(NSUInteger)index { - return translateErrors([&] { - return RLMCreateObjectAccessor(_realm, *_info, _results.get(index)); - }); -} - -- (id)firstObject { - auto row = translateErrors([&] { return _results.first(); }); - return row ? RLMCreateObjectAccessor(_realm, *_info, *row) : nil; -} - -- (id)lastObject { - auto row = translateErrors([&] { return _results.last(); }); - return row ? RLMCreateObjectAccessor(_realm, *_info, *row) : nil; -} - -- (NSUInteger)indexOfObject:(RLMObject *)object { - if (!object || (!object->_realm && !object.invalidated)) { - return NSNotFound; - } - - return translateErrors([&] { - return RLMConvertNotFound(_results.index_of(object->_row)); - }); -} - -- (id)valueForKeyPath:(NSString *)keyPath { - if ([keyPath characterAtIndex:0] == '@') { - if ([keyPath isEqualToString:@"@count"]) { - return @(self.count); - } - NSRange operatorRange = [keyPath rangeOfString:@"." options:NSLiteralSearch]; - NSUInteger keyPathLength = keyPath.length; - NSUInteger separatorIndex = operatorRange.location != NSNotFound ? operatorRange.location : keyPathLength; - NSString *operatorName = [keyPath substringWithRange:NSMakeRange(1, separatorIndex - 1)]; - SEL opSelector = NSSelectorFromString([NSString stringWithFormat:@"_%@ForKeyPath:", operatorName]); - BOOL isValidOperator = [self respondsToSelector:opSelector]; - if (!isValidOperator) { - @throw RLMException(@"Unsupported KVC collection operator found in key path '%@'", keyPath); - } - else if (separatorIndex >= keyPathLength - 1) { - @throw RLMException(@"Missing key path for KVC collection operator %@ in key path '%@'", operatorName, keyPath); - } - NSString *operatorKeyPath = [keyPath substringFromIndex:separatorIndex + 1]; - if (isValidOperator) { - return ((id(*)(id, SEL, id))objc_msgSend)(self, opSelector, operatorKeyPath); - } - } - return [super valueForKeyPath:keyPath]; -} - -- (id)valueForKey:(NSString *)key { - return translateErrors([&] { - return RLMCollectionValueForKey(self, key); - }); -} - -- (void)setValue:(id)value forKey:(NSString *)key { - translateErrors([&] { RLMResultsValidateInWriteTransaction(self); }); - RLMCollectionSetValueForKey(self, key, value); -} - -- (NSNumber *)_aggregateForKeyPath:(NSString *)keyPath method:(util::Optional (Results::*)(size_t))method - methodName:(NSString *)methodName returnNilForEmpty:(BOOL)returnNilForEmpty { - assertKeyPathIsNotNested(keyPath); - return [self aggregate:keyPath method:method methodName:methodName returnNilForEmpty:returnNilForEmpty]; -} - -- (NSNumber *)_minForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::min methodName:@"@min" returnNilForEmpty:YES]; -} - -- (NSNumber *)_maxForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::max methodName:@"@max" returnNilForEmpty:YES]; -} - -- (NSNumber *)_sumForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::sum methodName:@"@sum" returnNilForEmpty:NO]; -} - -- (NSNumber *)_avgForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::average methodName:@"@avg" returnNilForEmpty:YES]; -} - -- (NSArray *)_unionOfObjectsForKeyPath:(NSString *)keyPath { - assertKeyPathIsNotNested(keyPath); - return translateErrors([&] { - return RLMCollectionValueForKey(self, keyPath); - }); -} - -- (NSArray *)_distinctUnionOfObjectsForKeyPath:(NSString *)keyPath { - return [NSSet setWithArray:[self _unionOfObjectsForKeyPath:keyPath]].allObjects; -} - -- (NSArray *)_unionOfArraysForKeyPath:(NSString *)keyPath { - assertKeyPathIsNotNested(keyPath); - if ([keyPath isEqualToString:@"self"]) { - @throw RLMException(@"self is not a valid key-path for a KVC array collection operator as 'unionOfArrays'."); - } - - return translateErrors([&] { - NSArray *nestedResults = RLMCollectionValueForKey(self, keyPath); - NSMutableArray *flatArray = [NSMutableArray arrayWithCapacity:nestedResults.count]; - for (id array in nestedResults) { - NSArray *nsArray = RLMCollectionValueForKey(array, @"self"); - [flatArray addObjectsFromArray:nsArray]; - } - return flatArray; - }); -} - -- (NSArray *)_distinctUnionOfArraysForKeyPath:(__unused NSString *)keyPath { - return [NSSet setWithArray:[self _unionOfArraysForKeyPath:keyPath]].allObjects; -} - -- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ... { - va_list args; - va_start(args, predicateFormat); - RLMResults *results = [self objectsWhere:predicateFormat args:args]; - va_end(args); - return results; -} - -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args { - return [self objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]]; -} - -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate { - return translateErrors([&] { - if (_results.get_mode() == Results::Mode::Empty) { - return self; - } - auto query = RLMPredicateToQuery(predicate, _info->rlmObjectSchema, _realm.schema, _realm.group); - return [RLMResults resultsWithObjectInfo:*_info results:_results.filter(std::move(query))]; - }); -} - -- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending { - return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]]; -} - -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { - if (properties.count == 0) { - return self; - } - return translateErrors([&] { - if (_results.get_mode() == Results::Mode::Empty) { - return self; - } - - return [RLMResults resultsWithObjectInfo:*_info results:_results.sort(RLMSortDescriptorFromDescriptors(*_info->table(), properties))]; - }); -} - -- (id)objectAtIndexedSubscript:(NSUInteger)index { - return [self objectAtIndex:index]; -} - -- (id)aggregate:(NSString *)property method:(util::Optional (Results::*)(size_t))method - methodName:(NSString *)methodName returnNilForEmpty:(BOOL)returnNilForEmpty { - if (_results.get_mode() == Results::Mode::Empty) { - return returnNilForEmpty ? nil : @0; - } - size_t column = _info->tableColumn(property); - auto value = translateErrors([&] { return (_results.*method)(column); }, methodName); - if (!value) { - return nil; - } - return RLMMixedToObjc(*value); -} - -- (id)minOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::min methodName:@"minOfProperty" returnNilForEmpty:YES]; -} - -- (id)maxOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::max methodName:@"maxOfProperty" returnNilForEmpty:YES]; -} - -- (id)sumOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::sum methodName:@"sumOfProperty" returnNilForEmpty:NO]; -} - -- (id)averageOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::average methodName:@"averageOfProperty" returnNilForEmpty:YES]; -} - -- (void)deleteObjectsFromRealm { - return translateErrors([&] { - if (_results.get_mode() == Results::Mode::Table) { - RLMResultsValidateInWriteTransaction(self); - RLMClearTable(*_info); - } - else { - RLMTrackDeletions(_realm, ^{ _results.clear(); }); - } - }); -} - -- (NSString *)description { - return RLMDescriptionWithMaxDepth(@"RLMResults", self, RLMDescriptionMaxDepth); -} - -- (NSUInteger)indexInSource:(NSUInteger)index { - return translateErrors([&] { return _results.get(index).get_index(); }); -} - -- (realm::TableView)tableView { - return translateErrors([&] { return _results.get_tableview(); }); -} - -// The compiler complains about the method's argument type not matching due to -// it not having the generic type attached, but it doesn't seem to be possible -// to actually include the generic type -// http://www.openradar.me/radar?id=6135653276319744 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wmismatched-parameter-types" -- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMResults *, RLMCollectionChange *, NSError *))block { - [_realm verifyNotificationsAreSupported]; - return RLMAddNotificationBlock(self, _results, block, true); -} -#pragma clang diagnostic pop - -- (BOOL)isAttached -{ - return !!_realm; -} - -@end - -@implementation RLMLinkingObjects -@end diff --git a/Example/Pods/Realm/Realm/RLMSchema.mm b/Example/Pods/Realm/Realm/RLMSchema.mm deleted file mode 100644 index a3899bd..0000000 --- a/Example/Pods/Realm/Realm/RLMSchema.mm +++ /dev/null @@ -1,338 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMSchema_Private.h" - -#import "RLMAccessor.h" -#import "RLMObject_Private.hpp" -#import "RLMObjectSchema_Private.hpp" -#import "RLMProperty_Private.h" -#import "RLMRealm_Private.hpp" -#import "RLMSwiftSupport.h" -#import "RLMUtil.hpp" - -#import "object_store.hpp" -#import "schema.hpp" - -#import - -#import -#include - -using namespace realm; - -const uint64_t RLMNotVersioned = realm::ObjectStore::NotVersioned; - -// RLMSchema private properties -@interface RLMSchema () -@property (nonatomic, readwrite) NSMutableDictionary *objectSchemaByName; -@end - -static RLMSchema *s_sharedSchema = [[RLMSchema alloc] init]; -static NSMutableDictionary *s_localNameToClass = [[NSMutableDictionary alloc] init]; -static NSMutableDictionary *s_privateObjectSubclasses = [[NSMutableDictionary alloc] init]; - -static enum class SharedSchemaState { - Uninitialized, - Initializing, - Initialized -} s_sharedSchemaState = SharedSchemaState::Uninitialized; - -@implementation RLMSchema { - NSArray *_objectSchema; - realm::Schema _objectStoreSchema; -} - -// Caller must @synchronize on s_localNameToClass -static RLMObjectSchema *RLMRegisterClass(Class cls) { - if (RLMObjectSchema *schema = s_privateObjectSubclasses[[cls className]]) { - return schema; - } - - auto prevState = s_sharedSchemaState; - s_sharedSchemaState = SharedSchemaState::Initializing; - RLMObjectSchema *schema = [RLMObjectSchema schemaForObjectClass:cls]; - s_sharedSchemaState = prevState; - - // set unmanaged class on shared shema for unmanaged object creation - schema.unmanagedClass = RLMUnmanagedAccessorClassForObjectClass(schema.objectClass, schema); - - // override sharedSchema class methods for performance - RLMReplaceSharedSchemaMethod(cls, schema); - - s_privateObjectSubclasses[schema.className] = schema; - if ([cls shouldIncludeInDefaultSchema] && prevState != SharedSchemaState::Initialized) { - s_sharedSchema.objectSchemaByName[schema.className] = schema; - } - - return schema; -} - -// Caller must @synchronize on s_localNameToClass -static void RLMRegisterClassLocalNames(Class *classes, NSUInteger count) { - for (NSUInteger i = 0; i < count; i++) { - Class cls = classes[i]; - - if (!RLMIsObjectSubclass(cls) || RLMIsGeneratedClass(cls)) { - continue; - } - - NSString *className = NSStringFromClass(cls); - if ([RLMSwiftSupport isSwiftClassName:className]) { - className = [RLMSwiftSupport demangleClassName:className]; - } - // NSStringFromClass demangles the names for top-level Swift classes - // but not for nested classes. _T indicates it's a Swift symbol, t - // indicates it's a type, and C indicates it's a class. - else if ([className hasPrefix:@"_TtC"]) { - @throw RLMException(@"RLMObject subclasses cannot be nested within other declarations. Please move %@ to global scope.", className); - } - - if (Class existingClass = s_localNameToClass[className]) { - if (existingClass != cls) { - @throw RLMException(@"RLMObject subclasses with the same name cannot be included twice in the same target. " - @"Please make sure '%@' is only linked once to your current target.", className); - } - continue; - } - - s_localNameToClass[className] = cls; - RLMReplaceClassNameMethod(cls, className); - } -} - -- (instancetype)init { - self = [super init]; - if (self) { - _objectSchemaByName = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (NSArray *)objectSchema { - if (!_objectSchema) { - _objectSchema = [_objectSchemaByName allValues]; - } - return _objectSchema; -} - -- (void)setObjectSchema:(NSArray *)objectSchema { - _objectSchema = objectSchema; - _objectSchemaByName = [NSMutableDictionary dictionaryWithCapacity:objectSchema.count]; - for (RLMObjectSchema *object in objectSchema) { - [_objectSchemaByName setObject:object forKey:object.className]; - } -} - -- (RLMObjectSchema *)schemaForClassName:(NSString *)className { - if (RLMObjectSchema *schema = _objectSchemaByName[className]) { - return schema; // fast path for already-initialized schemas - } else if (Class cls = [RLMSchema classForString:className]) { - [cls sharedSchema]; // initialize the schema - return _objectSchemaByName[className]; // try again - } else { - return nil; - } -} - -- (RLMObjectSchema *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)className { - RLMObjectSchema *schema = [self schemaForClassName:className]; - if (!schema) { - @throw RLMException(@"Object type '%@' not managed by the Realm", className); - } - return schema; -} - -+ (instancetype)schemaWithObjectClasses:(NSArray *)classes { - NSUInteger count = classes.count; - auto classArray = std::make_unique<__unsafe_unretained Class[]>(count); - [classes getObjects:classArray.get() range:NSMakeRange(0, count)]; - - RLMSchema *schema = [[self alloc] init]; - @synchronized(s_localNameToClass) { - RLMRegisterClassLocalNames(classArray.get(), count); - - schema->_objectSchemaByName = [NSMutableDictionary dictionaryWithCapacity:count]; - for (Class cls in classes) { - if (!RLMIsObjectSubclass(cls)) { - @throw RLMException(@"Can't add non-Object type '%@' to a schema.", cls); - } - schema->_objectSchemaByName[[cls className]] = RLMRegisterClass(cls); - } - } - - NSMutableArray *errors = [NSMutableArray new]; - // Verify that all of the targets of links are included in the class list - [schema->_objectSchemaByName enumerateKeysAndObjectsUsingBlock:^(id, RLMObjectSchema *objectSchema, BOOL *) { - for (RLMProperty *prop in objectSchema.properties) { - if (prop.type != RLMPropertyTypeObject && prop.type != RLMPropertyTypeArray) { - continue; - } - if (!schema->_objectSchemaByName[prop.objectClassName]) { - [errors addObject:[NSString stringWithFormat:@"- '%@.%@' links to class '%@', which is missing from the list of classes managed by the Realm", objectSchema.className, prop.name, prop.objectClassName]]; - } - } - }]; - if (errors.count) { - @throw RLMException(@"Invalid class subset list:\n%@", [errors componentsJoinedByString:@"\n"]); - } - - return schema; -} - -+ (RLMObjectSchema *)sharedSchemaForClass:(Class)cls { - @synchronized(s_localNameToClass) { - // We create instances of Swift objects during schema init, and they - // obviously need to not also try to initialize the schema - if (s_sharedSchemaState == SharedSchemaState::Initializing) { - return nil; - } - - RLMRegisterClassLocalNames(&cls, 1); - return RLMRegisterClass(cls); - } -} - -+ (instancetype)partialSharedSchema { - return s_sharedSchema; -} - -// schema based on runtime objects -+ (instancetype)sharedSchema { - @synchronized(s_localNameToClass) { - // We replace this method with one which just returns s_sharedSchema - // once initialization is complete, but we still need to check if it's - // already complete because it may have been done by another thread - // while we were waiting for the lock - if (s_sharedSchemaState == SharedSchemaState::Initialized) { - return s_sharedSchema; - } - - if (s_sharedSchemaState == SharedSchemaState::Initializing) { - @throw RLMException(@"Illegal recursive call of +[%@ %@]. Note: Properties of Swift `Object` classes must not be prepopulated with queried results from a Realm.", self, NSStringFromSelector(_cmd)); - } - - s_sharedSchemaState = SharedSchemaState::Initializing; - try { - // Make sure we've discovered all classes - { - unsigned int numClasses; - using malloc_ptr = std::unique_ptr<__unsafe_unretained Class[], decltype(&free)>; - malloc_ptr classes(objc_copyClassList(&numClasses), &free); - RLMRegisterClassLocalNames(classes.get(), numClasses); - } - - [s_localNameToClass enumerateKeysAndObjectsUsingBlock:^(NSString *, Class cls, BOOL *) { - RLMRegisterClass(cls); - }]; - } - catch (...) { - s_sharedSchemaState = SharedSchemaState::Uninitialized; - throw; - } - - // Replace this method with one that doesn't need to acquire a lock - Class metaClass = objc_getMetaClass(class_getName(self)); - IMP imp = imp_implementationWithBlock(^{ return s_sharedSchema; }); - class_replaceMethod(metaClass, @selector(sharedSchema), imp, "@@:"); - - s_sharedSchemaState = SharedSchemaState::Initialized; - } - - return s_sharedSchema; -} - -// schema based on tables in a realm -+ (instancetype)dynamicSchemaFromObjectStoreSchema:(Schema const&)objectStoreSchema { - // cache descriptors for all subclasses of RLMObject - NSMutableArray *schemaArray = [NSMutableArray arrayWithCapacity:objectStoreSchema.size()]; - for (auto &objectSchema : objectStoreSchema) { - RLMObjectSchema *schema = [RLMObjectSchema objectSchemaForObjectStoreSchema:objectSchema]; - [schemaArray addObject:schema]; - } - - // set class array and mapping - RLMSchema *schema = [RLMSchema new]; - schema.objectSchema = schemaArray; - return schema; -} - -+ (Class)classForString:(NSString *)className { - if (Class cls = s_localNameToClass[className]) { - return cls; - } - - if (Class cls = NSClassFromString(className)) { - return RLMIsObjectSubclass(cls) ? cls : nil; - } - - // className might be the local name of a Swift class we haven't registered - // yet, so scan them all then recheck - { - unsigned int numClasses; - std::unique_ptr<__unsafe_unretained Class[], decltype(&free)> classes(objc_copyClassList(&numClasses), &free); - RLMRegisterClassLocalNames(classes.get(), numClasses); - } - - return s_localNameToClass[className]; -} - -- (id)copyWithZone:(NSZone *)zone { - RLMSchema *schema = [[RLMSchema allocWithZone:zone] init]; - schema->_objectSchemaByName = [[NSMutableDictionary allocWithZone:zone] - initWithDictionary:_objectSchemaByName copyItems:YES]; - return schema; -} - -- (BOOL)isEqualToSchema:(RLMSchema *)schema { - if (_objectSchemaByName.count != schema->_objectSchemaByName.count) { - return NO; - } - __block BOOL matches = YES; - [_objectSchemaByName enumerateKeysAndObjectsUsingBlock:^(NSString *name, RLMObjectSchema *objectSchema, BOOL *stop) { - if (![schema->_objectSchemaByName[name] isEqualToObjectSchema:objectSchema]) { - *stop = YES; - matches = NO; - } - }]; - return matches; -} - -- (NSString *)description { - NSMutableString *objectSchemaString = [NSMutableString string]; - NSArray *sort = @[[NSSortDescriptor sortDescriptorWithKey:@"className" ascending:YES]]; - for (RLMObjectSchema *objectSchema in [self.objectSchema sortedArrayUsingDescriptors:sort]) { - [objectSchemaString appendFormat:@"\t%@\n", - [objectSchema.description stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"]]; - } - return [NSString stringWithFormat:@"Schema {\n%@}", objectSchemaString]; -} - -- (Schema)objectStoreCopy { - if (_objectStoreSchema.size() == 0) { - std::vector schema; - schema.reserve(_objectSchemaByName.count); - [_objectSchemaByName enumerateKeysAndObjectsUsingBlock:[&](NSString *, RLMObjectSchema *objectSchema, BOOL *) { - schema.push_back(objectSchema.objectStoreCopy); - }]; - _objectStoreSchema = std::move(schema); - } - return _objectStoreSchema; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSwiftSupport.m b/Example/Pods/Realm/Realm/RLMSwiftSupport.m deleted file mode 100644 index e16c79e..0000000 --- a/Example/Pods/Realm/Realm/RLMSwiftSupport.m +++ /dev/null @@ -1,31 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMSwiftSupport.h" - -@implementation RLMSwiftSupport - -+ (BOOL)isSwiftClassName:(NSString *)className { - return [className rangeOfString:@"."].location != NSNotFound; -} - -+ (NSString *)demangleClassName:(NSString *)className { - return [className substringFromIndex:[className rangeOfString:@"."].location + 1]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncConfiguration.mm b/Example/Pods/Realm/Realm/RLMSyncConfiguration.mm deleted file mode 100644 index 65bfaf6..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncConfiguration.mm +++ /dev/null @@ -1,157 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncConfiguration_Private.hpp" - -#import "RLMSyncManager_Private.h" -#import "RLMSyncSession_Private.hpp" -#import "RLMSyncUser_Private.hpp" -#import "RLMSyncUtil_Private.hpp" -#import "RLMUtil.hpp" - -#import "sync/sync_manager.hpp" -#import "sync/sync_config.hpp" - -using namespace realm; - -namespace { -RLMSyncSessionErrorKind errorKindForSessionError(SyncSessionError error) { - switch (error) { - case SyncSessionError::AccessDenied: return RLMSyncSessionErrorKindAccessDenied; - case SyncSessionError::Debug: return RLMSyncSessionErrorKindDebug; - case SyncSessionError::SessionFatal: return RLMSyncSessionErrorKindSessionFatal; - case SyncSessionError::UserFatal: return RLMSyncSessionErrorKindUserFatal; - } - REALM_UNREACHABLE(); -} -} - -static BOOL isValidRealmURL(NSURL *url) { - NSString *scheme = [url scheme]; - if (![scheme isEqualToString:@"realm"] && ![scheme isEqualToString:@"realms"]) { - return NO; - } - return YES; -} - -@interface RLMSyncConfiguration () { - std::unique_ptr _config; -} - -- (instancetype)initWithUser:(RLMSyncUser *)user - realmURL:(NSURL *)url - customFileURL:(nullable NSURL *)customFileURL - stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function)errorHandler; -@end - -@implementation RLMSyncConfiguration - -@dynamic stopPolicy; - -- (instancetype)initWithRawConfig:(realm::SyncConfig)config { - if (self = [super init]) { - _config = std::make_unique(config); - } - return self; -} - -- (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[RLMSyncConfiguration class]]) { - return NO; - } - RLMSyncConfiguration *that = (RLMSyncConfiguration *)object; - return [self.realmURL isEqual:that.realmURL] - && [self.user isEqual:that.user] - && self.stopPolicy == that.stopPolicy; -} - -- (realm::SyncConfig)rawConfiguration { - return *_config; -} - -- (RLMSyncUser *)user { - return [[RLMSyncUser alloc] initWithSyncUser:_config->user]; -} - -- (RLMSyncStopPolicy)stopPolicy { - return translateStopPolicy(_config->stop_policy); -} - -- (void)setStopPolicy:(RLMSyncStopPolicy)stopPolicy { - _config->stop_policy = translateStopPolicy(stopPolicy); -} - -- (NSURL *)realmURL { - NSString *rawStringURL = @(_config->realm_url.c_str()); - return [NSURL URLWithString:rawStringURL]; -} - -- (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url { - return [self initWithUser:user - realmURL:url - customFileURL:nil - stopPolicy:RLMSyncStopPolicyAfterChangesUploaded - errorHandler:nullptr]; -} - -- (instancetype)initWithUser:(RLMSyncUser *)user - realmURL:(NSURL *)url - customFileURL:(nullable NSURL *)customFileURL - stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function)errorHandler { - if (self = [super init]) { - if (!isValidRealmURL(url)) { - @throw RLMException(@"The provided URL (%@) was not a valid Realm URL.", [url absoluteString]); - } - auto bindHandler = [=](const std::string& path, - const SyncConfig& config, - const std::shared_ptr& session) { - [user _bindSessionWithPath:path - config:config - session:session - completion:[RLMSyncManager sharedManager].sessionCompletionNotifier - isStandalone:NO]; - }; - if (!errorHandler) { - errorHandler = [=](std::shared_ptr errored_session, - int error_code, - std::string message, - realm::SyncSessionError error_type) { - RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session]; - [[RLMSyncManager sharedManager] _fireErrorWithCode:error_code - message:@(message.c_str()) - session:session - errorClass:errorKindForSessionError(error_type)]; - }; - } - - _config = std::make_unique(SyncConfig{ - [user _syncUser], - [[url absoluteString] UTF8String], - translateStopPolicy(stopPolicy), - std::move(bindHandler), - std::move(errorHandler) - }); - self.customFileURL = customFileURL; - return self; - } - return nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncCredentials.m b/Example/Pods/Realm/Realm/RLMSyncCredentials.m deleted file mode 100644 index 03669e6..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncCredentials.m +++ /dev/null @@ -1,96 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncCredentials.h" -#import "RLMSyncUtil_Private.h" - -/// A Twitter account as an identity provider. -//extern RLMIdentityProvider const RLMIdentityProviderTwitter; - -RLMIdentityProvider const RLMIdentityProviderDebug = @"debug"; -RLMIdentityProvider const RLMIdentityProviderRealm = @"realm"; -RLMIdentityProvider const RLMIdentityProviderUsernamePassword = @"password"; -RLMIdentityProvider const RLMIdentityProviderFacebook = @"facebook"; -RLMIdentityProvider const RLMIdentityProviderTwitter = @"twitter"; -RLMIdentityProvider const RLMIdentityProviderGoogle = @"google"; -RLMIdentityProvider const RLMIdentityProviderCloudKit = @"cloudkit"; - -@interface RLMSyncCredentials () - -- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token - provider:(RLMIdentityProvider)provider - userInfo:(NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER; - -@property (nonatomic, readwrite) RLMSyncCredentialsToken token; -@property (nonatomic, readwrite) RLMIdentityProvider provider; -@property (nonatomic, readwrite) NSDictionary *userInfo; - -@end - -@implementation RLMSyncCredentials - -+ (instancetype)credentialsWithFacebookToken:(RLMSyncCredentialsToken)token { - return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderFacebook userInfo:nil]; -} - -+ (instancetype)credentialsWithGoogleToken:(RLMSyncCredentialsToken)token { - return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderGoogle userInfo:nil]; -} - -+ (instancetype)credentialsWithCloudKitToken:(RLMSyncCredentialsToken)token { - return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderCloudKit userInfo:nil]; -} - -+ (instancetype)credentialsWithUsername:(NSString *)username - password:(NSString *)password - register:(BOOL)shouldRegister { - return [[self alloc] initWithCustomToken:username - provider:RLMIdentityProviderUsernamePassword - userInfo:@{kRLMSyncPasswordKey: password, - kRLMSyncRegisterKey: @(shouldRegister)}]; -} - -+ (instancetype)credentialsWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity { - return [[self alloc] initWithCustomToken:accessToken - provider:RLMIdentityProviderAccessToken - userInfo:@{kRLMSyncIdentityKey: identity}]; -} - -- (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[RLMSyncCredentials class]]) { - return NO; - } - RLMSyncCredentials *that = (RLMSyncCredentials *)object; - return ([self.token isEqualToString:that.token] - && [self.provider isEqualToString:that.provider] - && [self.userInfo isEqual:that.userInfo]); -} - -- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token - provider:(RLMIdentityProvider)provider - userInfo:(NSDictionary *)userInfo { - if (self = [super init]) { - self.token = token; - self.provider = provider; - self.userInfo = userInfo; - return self; - } - return nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncErrorResponseModel.m b/Example/Pods/Realm/Realm/RLMSyncErrorResponseModel.m deleted file mode 100644 index 5e75139..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncErrorResponseModel.m +++ /dev/null @@ -1,48 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncErrorResponseModel.h" - -static const NSString *const kRLMSyncErrorStatusKey = @"status"; -static const NSString *const kRLMSyncErrorCodeKey = @"code"; -static const NSString *const kRLMSyncErrorTitleKey = @"title"; -static const NSString *const kRLMSyncErrorHintKey = @"hint"; - -@interface RLMSyncErrorResponseModel () - -@property (nonatomic, readwrite) NSInteger status; -@property (nonatomic, readwrite) NSInteger code; -@property (nonatomic, readwrite) NSString *title; -@property (nonatomic, readwrite) NSString *hint; - -@end - -@implementation RLMSyncErrorResponseModel - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary { - if (self = [super init]) { - RLM_SYNC_PARSE_DOUBLE_OR_ABORT(jsonDictionary, kRLMSyncErrorStatusKey, status); - RLM_SYNC_PARSE_DOUBLE_OR_ABORT(jsonDictionary, kRLMSyncErrorCodeKey, code); - RLM_SYNC_PARSE_OPTIONAL_STRING(jsonDictionary, kRLMSyncErrorTitleKey, title); - RLM_SYNC_PARSE_OPTIONAL_STRING(jsonDictionary, kRLMSyncErrorHintKey, hint); - return self; - } - return nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncManager.mm b/Example/Pods/Realm/Realm/RLMSyncManager.mm deleted file mode 100644 index a26a804..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncManager.mm +++ /dev/null @@ -1,205 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncManager_Private.h" - -#import "RLMRealmConfiguration+Sync.h" -#import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncSession_Private.hpp" -#import "RLMSyncUser_Private.hpp" -#import "RLMUtil.hpp" - -#import "sync/sync_config.hpp" -#import "sync/sync_manager.hpp" -#import "sync/sync_session.hpp" - -using namespace realm; -using Level = realm::util::Logger::Level; - -namespace { - -Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) { - switch (logLevel) { - case RLMSyncLogLevelOff: return Level::off; - case RLMSyncLogLevelFatal: return Level::fatal; - case RLMSyncLogLevelError: return Level::error; - case RLMSyncLogLevelWarn: return Level::warn; - case RLMSyncLogLevelInfo: return Level::info; - case RLMSyncLogLevelDetail: return Level::detail; - case RLMSyncLogLevelDebug: return Level::debug; - case RLMSyncLogLevelTrace: return Level::trace; - case RLMSyncLogLevelAll: return Level::all; - } - REALM_UNREACHABLE(); // Unrecognized log level. -} - -RLMSyncLogLevel logLevelForLevel(Level logLevel) { - switch (logLevel) { - case Level::off: return RLMSyncLogLevelOff; - case Level::fatal: return RLMSyncLogLevelFatal; - case Level::error: return RLMSyncLogLevelError; - case Level::warn: return RLMSyncLogLevelWarn; - case Level::info: return RLMSyncLogLevelInfo; - case Level::detail: return RLMSyncLogLevelDetail; - case Level::debug: return RLMSyncLogLevelDebug; - case Level::trace: return RLMSyncLogLevelTrace; - case Level::all: return RLMSyncLogLevelAll; - } - REALM_UNREACHABLE(); // Unrecognized log level. -} - -struct CocoaSyncLogger : public realm::util::RootLogger { - void do_log(Level, std::string message) override { - NSLog(@"Sync: %@", RLMStringDataToNSString(message)); - } -}; - -struct CocoaSyncLoggerFactory : public realm::SyncLoggerFactory { - std::unique_ptr make_logger(realm::util::Logger::Level level) override { - auto logger = std::make_unique(); - logger->set_level_threshold(level); - return std::move(logger); - } -} s_syncLoggerFactory; - -} // anonymous namespace - -@interface RLMSyncManager () -- (instancetype)initWithCustomRootDirectory:(nullable NSURL *)rootDirectory NS_DESIGNATED_INITIALIZER; -@end - -@implementation RLMSyncManager - -static RLMSyncManager *s_sharedManager = nil; -static dispatch_once_t s_onceToken; - -+ (instancetype)sharedManager { - dispatch_once(&s_onceToken, ^{ - s_sharedManager = [[RLMSyncManager alloc] initWithCustomRootDirectory:nil]; - }); - return s_sharedManager; -} - -- (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory { - if (self = [super init]) { - // Create the global error handler. - auto errorLambda = [=](int error_code, std::string message) { - NSError *error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:@{@"description": @(message.c_str()), - @"error": @(error_code)}]; - [self _fireError:error]; - }; - - // Initialize the sync engine. - SyncManager::shared().set_logger_factory(s_syncLoggerFactory); - SyncManager::shared().set_error_handler(errorLambda); - bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground(); - auto mode = should_encrypt ? SyncManager::MetadataMode::Encryption : SyncManager::MetadataMode::NoEncryption; - rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)]; - SyncManager::shared().configure_file_system(rootDirectory.path.UTF8String, mode, none, true); - return self; - } - return nil; -} - -- (NSString *)appID { - if (!_appID) { - _appID = [[NSBundle mainBundle] bundleIdentifier] ?: @"(none)"; - } - return _appID; -} - -#pragma mark - Passthrough properties - -- (RLMSyncLogLevel)logLevel { - return logLevelForLevel(realm::SyncManager::shared().log_level()); -} - -- (void)setLogLevel:(RLMSyncLogLevel)logLevel { - realm::SyncManager::shared().set_log_level(levelForSyncLogLevel(logLevel)); -} - -- (BOOL)disableSSLValidation { - return realm::SyncManager::shared().client_should_validate_ssl(); -} - -- (void)setDisableSSLValidation:(BOOL)disableSSLValidation { - realm::SyncManager::shared().set_client_should_validate_ssl(!disableSSLValidation); -} - -#pragma mark - Private API - -- (void)_fireError:(NSError *)error { - dispatch_async(dispatch_get_main_queue(), ^{ - if (self.errorHandler) { - self.errorHandler(error, nil); - } - }); -} - -- (void)_fireErrorWithCode:(int)errorCode - message:(NSString *)message - session:(RLMSyncSession *)session - errorClass:(RLMSyncSessionErrorKind)errorClass { - NSError *error; - - switch (errorClass) { - case RLMSyncSessionErrorKindUserFatal: - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientUserError - userInfo:@{@"description": message, - @"error": @(errorCode)}]; - break; - case RLMSyncSessionErrorKindSessionFatal: - case RLMSyncSessionErrorKindAccessDenied: - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:@{@"description": message, - @"error": @(errorCode)}]; - break; - case RLMSyncSessionErrorKindDebug: - // Report the error. There's nothing the user can do about it, though. - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientInternalError - userInfo:@{@"description": message, - @"error": @(errorCode)}]; - break; - } - dispatch_async(dispatch_get_main_queue(), ^{ - if (!self.errorHandler - || (errorClass == RLMSyncSessionErrorKindDebug && self.logLevel >= RLMSyncLogLevelDebug)) { - return; - } - self.errorHandler(error, session); - }); -} - -- (NSArray *)_allUsers { - NSMutableArray *buffer = [NSMutableArray array]; - for (auto user : SyncManager::shared().all_logged_in_users()) { - [buffer addObject:[[RLMSyncUser alloc] initWithSyncUser:std::move(user)]]; - } - return buffer; -} - -+ (void)resetForTesting { - SyncManager::shared().reset_for_testing(); -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncPermissionChange.m b/Example/Pods/Realm/Realm/RLMSyncPermissionChange.m deleted file mode 100644 index 36e52d5..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncPermissionChange.m +++ /dev/null @@ -1,75 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncPermissionChange_Private.h" - -#import "RLMRealm.h" -#import "RLMRealmConfiguration+Sync.h" -#import "RLMSyncConfiguration.h" -#import "RLMSyncUser.h" - -@implementation RLMSyncPermissionChange - -+ (instancetype)permissionChangeWithRealmURL:(NSString *)realmURL - userID:(NSString *)userID - read:(nullable NSNumber *)mayRead - write:(nullable NSNumber *)mayWrite - manage:(nullable NSNumber *)mayManage { - RLMSyncPermissionChange *permissionChange = [RLMSyncPermissionChange new]; - permissionChange.realmUrl = realmURL; - permissionChange.userId = userID; - permissionChange.mayRead = mayRead; - permissionChange.mayWrite = mayWrite; - permissionChange.mayManage = mayManage; - return permissionChange; -} - -+ (NSArray *)requiredProperties { - return @[@"id", @"createdAt", @"updatedAt", @"realmUrl", @"userId"]; -} - -+ (NSDictionary *)defaultPropertyValues { - NSDate *now = [NSDate date]; - return @{ - @"id": [NSUUID UUID].UUIDString, - @"createdAt": now, - @"updatedAt": now, - @"realmUrl": @"*", - @"userId": @"*" - }; -} - -+ (BOOL)shouldIncludeInDefaultSchema { - return NO; -} - -- (RLMSyncManagementObjectStatus)status { - if (!self.statusCode) { - return RLMSyncManagementObjectStatusNotProcessed; - } - if (self.statusCode.integerValue == 0) { - return RLMSyncManagementObjectStatusSuccess; - } - return RLMSyncManagementObjectStatusError; -} - -+ (NSString *)_realmObjectName { - return @"PermissionChange"; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncSession.mm b/Example/Pods/Realm/Realm/RLMSyncSession.mm deleted file mode 100644 index 506c2cd..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncSession.mm +++ /dev/null @@ -1,110 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncSession_Private.hpp" - -#import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncUser_Private.hpp" -#import "sync/sync_session.hpp" - -using namespace realm; - -@interface RLMSyncSession () { - std::weak_ptr _session; -} - -@end - -@implementation RLMSyncSession - -- (instancetype)initWithSyncSession:(std::shared_ptr)session { - if (self = [super init]) { - _session = session; - return self; - } - return nil; -} - -- (RLMSyncConfiguration *)configuration { - if (auto session = _session.lock()) { - if (session->state() != SyncSession::PublicState::Error) { - return [[RLMSyncConfiguration alloc] initWithRawConfig:session->config()]; - } - } - return nil; -} - -- (NSURL *)realmURL { - if (auto session = _session.lock()) { - if (auto url = session->full_realm_url()) { - return [NSURL URLWithString:@(url->c_str())]; - } - } - return nil; -} - -- (RLMSyncUser *)parentUser { - if (auto session = _session.lock()) { - if (session->state() != SyncSession::PublicState::Error) { - return [[RLMSyncUser alloc] initWithSyncUser:session->user()]; - } - } - return nil; -} - -- (RLMSyncSessionState)state { - if (auto session = _session.lock()) { - if (session->state() == SyncSession::PublicState::Inactive) { - return RLMSyncSessionStateInactive; - } - if (session->state() != SyncSession::PublicState::Error) { - return RLMSyncSessionStateActive; - } - } - return RLMSyncSessionStateInvalid; -} - -- (BOOL)waitForUploadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)(void))callback { - if (auto session = _session.lock()) { - if (session->state() == SyncSession::PublicState::Error) { - return NO; - } - queue = queue ?: dispatch_get_main_queue(); - session->wait_for_upload_completion([=](std::error_code) { // FIXME: report error to user - dispatch_async(queue, callback); - }); - return YES; - } - return NO; -} - -- (BOOL)waitForDownloadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)(void))callback { - if (auto session = _session.lock()) { - if (session->state() == SyncSession::PublicState::Error) { - return NO; - } - queue = queue ?: dispatch_get_main_queue(); - session->wait_for_download_completion([=](std::error_code) { // FIXME: report error to user - dispatch_async(queue, callback); - }); - return YES; - } - return NO; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm b/Example/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm deleted file mode 100644 index 5112df4..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm +++ /dev/null @@ -1,159 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncSessionRefreshHandle.hpp" - -#import "RLMAuthResponseModel.h" -#import "RLMNetworkClient.h" -#import "RLMSyncManager_Private.h" -#import "RLMSyncUser_Private.hpp" -#import "RLMTokenModels.h" - -#import "sync/sync_session.hpp" - -using namespace realm; - -@interface RLMSyncSessionRefreshHandle () { - std::weak_ptr _session; -} - -@property (nonatomic, weak) RLMSyncUser *user; -@property (nonatomic, strong) NSString *fullURLPath; -@property (nonatomic) NSTimer *timer; - -@end - -@implementation RLMSyncSessionRefreshHandle - -- (instancetype)initWithFullURLPath:(NSString *)urlPath - user:(RLMSyncUser *)user - session:(std::shared_ptr)session { - if (self = [super init]) { - self.fullURLPath = urlPath; - self.user = user; - _session = session; - return self; - } - return nil; -} - -- (void)invalidate { - [self.timer invalidate]; - self.user = nil; -} - -- (void)scheduleRefreshTimer:(NSTimeInterval)fireTime { - static const NSInteger refreshBuffer = 10; - [self.timer invalidate]; - self.timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSince1970:(fireTime - refreshBuffer)] - interval:0 - target:self - selector:@selector(timerFired:) - userInfo:nil - repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode]; -} - -- (void)timerFired:(__unused NSTimer *)timer { - RLMSyncUser *user = self.user; - if (!user) { - return; - } - RLMServerToken refreshToken = user._refreshToken; - if (!refreshToken) { - [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; - [self.timer invalidate]; - return; - } - - NSDictionary *json = @{ - kRLMSyncProviderKey: @"realm", - kRLMSyncPathKey: self.fullURLPath, - kRLMSyncDataKey: refreshToken, - kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, - }; - - RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { - if (json && !error) { - RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json - requireAccessToken:YES - requireRefreshToken:NO]; - if (!model) { - // Malformed JSON - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; - [self.timer invalidate]; - [[RLMSyncManager sharedManager] _fireError:error]; - return; - } - - // Success - if (auto session = _session.lock()) { - if (session->state() != SyncSession::PublicState::Error) { - session->refresh_access_token([model.accessToken.token UTF8String], none); - [self scheduleRefreshTimer:model.accessToken.tokenData.expires]; - return; - } - } - // The session is dead or in a fatal error state. - [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; - [self.timer invalidate]; - return; - } - - // Something else went wrong - NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; - [[RLMSyncManager sharedManager] _fireError:syncError]; - NSTimeInterval nextFireDate = 0; - // Certain errors should trigger a retry. - if (error.domain == NSURLErrorDomain) { - switch (error.code) { - case NSURLErrorCannotConnectToHost: - // FIXME: 120 seconds is an arbitrarily chosen value, consider rationalizing it. - nextFireDate = [[NSDate dateWithTimeIntervalSinceNow:120] timeIntervalSince1970]; - break; - case NSURLErrorNotConnectedToInternet: - case NSURLErrorNetworkConnectionLost: - case NSURLErrorTimedOut: - case NSURLErrorDNSLookupFailed: - case NSURLErrorCannotFindHost: - // FIXME: 30 seconds is an arbitrarily chosen value, consider rationalizing it. - nextFireDate = [[NSDate dateWithTimeIntervalSinceNow:30] timeIntervalSince1970]; - break; - default: - break; - } - if (nextFireDate > 0) { - [self scheduleRefreshTimer:nextFireDate]; - } else { - [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; - [self.timer invalidate]; - } - } - }; - [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth - server:user.authenticationServer - JSON:json - completion:handler]; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncUser.mm b/Example/Pods/Realm/Realm/RLMSyncUser.mm deleted file mode 100644 index 3a2b4b2..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncUser.mm +++ /dev/null @@ -1,338 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncUser_Private.hpp" - -#import "RLMAuthResponseModel.h" -#import "RLMNetworkClient.h" -#import "RLMSyncManager_Private.h" -#import "RLMSyncSession_Private.hpp" -#import "RLMSyncSessionRefreshHandle.hpp" -#import "RLMTokenModels.h" -#import "RLMUtil.hpp" - -#import "sync/sync_manager.hpp" -#import "sync/sync_session.hpp" -#import "sync/sync_user.hpp" - -using namespace realm; - -@interface RLMSyncUser () { - std::shared_ptr _user; -} - -- (instancetype)initWithAuthServer:(nullable NSURL *)authServer NS_DESIGNATED_INITIALIZER; - -@property (nonatomic, readwrite) NSURL *authenticationServer; -@property (nonatomic) NSMutableDictionary *refreshHandles; - -@end - -@implementation RLMSyncUser - -#pragma mark - static API - -+ (NSDictionary *)allUsers { - NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers]; - return [NSDictionary dictionaryWithObjects:allUsers - forKeys:[allUsers valueForKey:@"identity"]]; -} - -+ (RLMSyncUser *)currentUser { - NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers]; - if (allUsers.count > 1) { - @throw RLMException(@"+currentUser cannot be called if more that one valid, logged-in user exists."); - } - return allUsers.firstObject; -} - -#pragma mark - API - -- (instancetype)initWithAuthServer:(nullable NSURL *)authServer { - if (self = [super init]) { - self.authenticationServer = authServer; - return self; - } - return nil; -} - -- (instancetype)initWithSyncUser:(std::shared_ptr)user { - NSString *rawServerURL = @(user->server_url().c_str()); - if (self = [self initWithAuthServer:[NSURL URLWithString:rawServerURL]]) { - _user = user; - return self; - } - return nil; -} - -- (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[RLMSyncUser class]]) { - return NO; - } - return _user == ((RLMSyncUser *)object)->_user; -} - -+ (void)logInWithCredentials:(RLMSyncCredentials *)credential - authServerURL:(NSURL *)authServerURL - onCompletion:(RLMUserCompletionBlock)completion { - [self logInWithCredentials:credential - authServerURL:authServerURL - timeout:30 - onCompletion:completion]; -} - -+ (void)logInWithCredentials:(RLMSyncCredentials *)credential - authServerURL:(NSURL *)authServerURL - timeout:(NSTimeInterval)timeout - onCompletion:(RLMUserCompletionBlock)completion { - RLMSyncUser *user = [[RLMSyncUser alloc] initWithAuthServer:authServerURL]; - [RLMSyncUser _performLogInForUser:user - credentials:credential - authServerURL:authServerURL - timeout:timeout - completionBlock:completion]; -} - -- (void)logOut { - if (!_user) { - return; - } - _user->log_out(); - for (id key in self.refreshHandles) { - [self.refreshHandles[key] invalidate]; - } - [self.refreshHandles removeAllObjects]; -} - -- (nullable RLMSyncSession *)sessionForURL:(NSURL *)url { - if (!_user) { - return nil; - } - auto path = SyncManager::shared().path_for_realm(_user->identity(), [url.absoluteString UTF8String]); - return [[RLMSyncSession alloc] initWithSyncSession:_user->session_for_on_disk_path(path)]; -} - -- (NSArray *)allSessions { - if (!_user) { - return @[]; - } - NSMutableArray *buffer = [NSMutableArray array]; - auto sessions = _user->all_sessions(); - for (auto session : sessions) { - [buffer addObject:[[RLMSyncSession alloc] initWithSyncSession:std::move(session)]]; - } - return [buffer copy]; -} - -- (NSString *)identity { - if (!_user) { - return nil; - } - return @(_user->identity().c_str()); -} - -- (RLMSyncUserState)state { - if (!_user) { - return RLMSyncUserStateError; - } - switch (_user->state()) { - case SyncUser::State::Active: - return RLMSyncUserStateActive; - case SyncUser::State::LoggedOut: - return RLMSyncUserStateLoggedOut; - case SyncUser::State::Error: - return RLMSyncUserStateError; - } -} - -- (RLMRealm *)managementRealmWithError:(NSError **)error { - return [RLMRealm realmWithConfiguration:[RLMRealmConfiguration managementConfigurationForUser:self] error:error]; -} - -#pragma mark - Private API - -- (void)_unregisterRefreshHandleForURLPath:(NSString *)path { - [self.refreshHandles removeObjectForKey:path]; -} - -- (NSString *)_refreshToken { - if (!_user) { - return nil; - } - return @(_user->refresh_token().c_str()); -} - -- (void)_bindSessionWithPath:(__unused const std::string&)path - config:(const SyncConfig&)config - session:(std::shared_ptr)session - completion:(RLMSyncBasicErrorReportingBlock)completion - isStandalone:(__unused BOOL)standalone { - NSURL *realmURL = [NSURL URLWithString:@(config.realm_url.c_str())]; - RLMServerPath unresolvedURL = [realmURL path]; - NSDictionary *json = @{ - kRLMSyncPathKey: unresolvedURL, - kRLMSyncProviderKey: @"realm", - kRLMSyncDataKey: @(_user->refresh_token().c_str()), - kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, - }; - - RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { - if (json && !error) { - RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json - requireAccessToken:YES - requireRefreshToken:NO]; - if (!model) { - // Malformed JSON - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - if (completion) { - completion(error); - } - [[RLMSyncManager sharedManager] _fireError:error]; - return; - } - - // SUCCESS - NSString *accessToken = model.accessToken.token; - RLMServerPath resolvedPath = model.accessToken.tokenData.path; - // Munge the path onto the original URL, because reasons. - NSURLComponents *urlBuffer = [NSURLComponents componentsWithURL:realmURL resolvingAgainstBaseURL:YES]; - urlBuffer.path = resolvedPath; - NSString *resolvedURLString = [[urlBuffer URL] absoluteString]; - if (!resolvedURLString) { - @throw RLMException(@"Resolved path returned from the server was invalid (%@).", resolvedPath); - } - // Refresh the access token. - session->refresh_access_token([accessToken UTF8String], {resolvedURLString.UTF8String}); - bool success = session->state() != SyncSession::PublicState::Error; - if (success) { - // Schedule the session for automatic refreshing on a timer. - auto handle = [[RLMSyncSessionRefreshHandle alloc] initWithFullURLPath:resolvedURLString - user:self - session:session]; - [self.refreshHandles[resolvedURLString] invalidate]; - self.refreshHandles[resolvedURLString] = handle; - [handle scheduleRefreshTimer:model.accessToken.tokenData.expires]; - } - if (completion) { - completion(success ? nil : [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]); - } - return; - } - - // Something else went wrong - NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; - if (completion) { - completion(syncError); - } - [[RLMSyncManager sharedManager] _fireError:syncError]; - }; - [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth - server:self.authenticationServer - JSON:json - completion:handler]; -} - -- (std::shared_ptr)_syncUser { - return _user; -} - -+ (void)_performLogInForUser:(RLMSyncUser *)user - credentials:(RLMSyncCredentials *)credentials - authServerURL:(NSURL *)authServerURL - timeout:(NSTimeInterval)timeout - completionBlock:(RLMUserCompletionBlock)completion { - // Special credential login should be treated differently. - if (credentials.provider == RLMIdentityProviderAccessToken) { - [self _performLoginForDirectAccessTokenCredentials:credentials user:user completionBlock:completion]; - return; - } - - // Prepare login network request - NSMutableDictionary *json = [@{ - kRLMSyncProviderKey: credentials.provider, - kRLMSyncDataKey: credentials.token, - kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, - } mutableCopy]; - NSMutableDictionary *info = [(credentials.userInfo ?: @{}) mutableCopy]; - - if ([info count] > 0) { - // Munge user info into the JSON request. - json[@"user_info"] = info; - } - - RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { - if (json && !error) { - RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json - requireAccessToken:NO - requireRefreshToken:YES]; - if (!model) { - // Malformed JSON - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - completion(nil, error); - return; - } else { - std::string server_url = authServerURL.absoluteString.UTF8String; - auto sync_user = SyncManager::shared().get_user([model.refreshToken.tokenData.identity UTF8String], - [model.refreshToken.token UTF8String], - std::move(server_url)); - if (!sync_user) { - completion(nil, [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]); - return; - } - user->_user = sync_user; - completion(user, nil); - } - } else { - // Something else went wrong - completion(nil, error); - } - }; - [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth - server:authServerURL - JSON:json - timeout:timeout - completion:handler]; -} - -+ (void)_performLoginForDirectAccessTokenCredentials:(RLMSyncCredentials *)credentials - user:(RLMSyncUser *)user - completionBlock:(nonnull RLMUserCompletionBlock)completion { - NSString *identity = credentials.userInfo[kRLMSyncIdentityKey]; - NSAssert(identity != nil, @"Improperly created direct access token credential."); - auto sync_user = SyncManager::shared().get_user([identity UTF8String], [credentials.token UTF8String], none, true); - if (!sync_user) { - completion(nil, [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]); - return; - } - user->_user = sync_user; - completion(user, nil); -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMSyncUtil.mm b/Example/Pods/Realm/Realm/RLMSyncUtil.mm deleted file mode 100644 index d6cafe7..0000000 --- a/Example/Pods/Realm/Realm/RLMSyncUtil.mm +++ /dev/null @@ -1,81 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil_Private.hpp" -#import "RLMSyncUser_Private.hpp" -#import "RLMRealmConfiguration+Sync.h" -#import "RLMRealmConfiguration_Private.hpp" -#import "RLMSyncPermissionChange.h" - -@implementation RLMRealmConfiguration (RealmSync) -+ (instancetype)managementConfigurationForUser:(RLMSyncUser *)user { - NSURLComponents *components = [NSURLComponents componentsWithURL:user.authenticationServer resolvingAgainstBaseURL:NO]; - if ([components.scheme isEqualToString:@"https"]) { - components.scheme = @"realms"; - } else { - components.scheme = @"realm"; - } - components.path = @"/~/__management"; - NSURL *managementRealmURL = components.URL; - RLMSyncConfiguration *syncConfig = [[RLMSyncConfiguration alloc] initWithUser:user realmURL:managementRealmURL]; - RLMRealmConfiguration *config = [RLMRealmConfiguration new]; - config.syncConfiguration = syncConfig; - config.objectClasses = @[RLMSyncPermissionChange.class]; - return config; -} -@end - -RLMIdentityProvider const RLMIdentityProviderAccessToken = @"_access_token"; - -NSString *const RLMSyncErrorDomain = @"io.realm.sync"; - -NSString *const kRLMSyncAppIDKey = @"app_id"; -NSString *const kRLMSyncDataKey = @"data"; -NSString *const kRLMSyncErrorJSONKey = @"json"; -NSString *const kRLMSyncErrorStatusCodeKey = @"statusCode"; -NSString *const kRLMSyncIdentityKey = @"identity"; -NSString *const kRLMSyncPasswordKey = @"password"; -NSString *const kRLMSyncPathKey = @"path"; -NSString *const kRLMSyncProviderKey = @"provider"; -NSString *const kRLMSyncRegisterKey = @"register"; -NSString *const kRLMSyncUnderlyingErrorKey = @"underlying_error"; - -namespace realm { - -SyncSessionStopPolicy translateStopPolicy(RLMSyncStopPolicy stopPolicy) { - switch (stopPolicy) { - case RLMSyncStopPolicyImmediately: return SyncSessionStopPolicy::Immediately; - case RLMSyncStopPolicyLiveIndefinitely: return SyncSessionStopPolicy::LiveIndefinitely; - case RLMSyncStopPolicyAfterChangesUploaded: return SyncSessionStopPolicy::AfterChangesUploaded; - } - REALM_UNREACHABLE(); // Unrecognized stop policy. -} - -RLMSyncStopPolicy translateStopPolicy(SyncSessionStopPolicy stop_policy) -{ - switch (stop_policy) { - case SyncSessionStopPolicy::Immediately: return RLMSyncStopPolicyImmediately; - case SyncSessionStopPolicy::LiveIndefinitely: return RLMSyncStopPolicyLiveIndefinitely; - case SyncSessionStopPolicy::AfterChangesUploaded: return RLMSyncStopPolicyAfterChangesUploaded; - } - REALM_UNREACHABLE(); -} - -} diff --git a/Example/Pods/Realm/Realm/RLMTokenModels.m b/Example/Pods/Realm/Realm/RLMTokenModels.m deleted file mode 100644 index e85e70e..0000000 --- a/Example/Pods/Realm/Realm/RLMTokenModels.m +++ /dev/null @@ -1,71 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMTokenModels.h" -#import "RLMSyncUtil_Private.h" - -static const NSString *const kRLMSyncTokenDataKey = @"token_data"; -static const NSString *const kRLMSyncTokenKey = @"token"; -static const NSString *const kRLMSyncExpiresKey = @"expires"; - -@interface RLMTokenDataModel () - -@property (nonatomic, readwrite) NSString *identity; -@property (nonatomic, readwrite) NSString *appID; -@property (nonatomic, readwrite) NSString *path; -@property (nonatomic, readwrite) NSTimeInterval expires; -//@property (nonatomic, readwrite) NSArray *access; - -@end - -@implementation RLMTokenDataModel - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary { - if (self = [super init]) { - RLM_SYNC_PARSE_STRING_OR_ABORT(jsonDictionary, kRLMSyncIdentityKey, identity); - RLM_SYNC_PARSE_OPTIONAL_STRING(jsonDictionary, kRLMSyncAppIDKey, appID); - RLM_SYNC_PARSE_OPTIONAL_STRING(jsonDictionary, kRLMSyncPathKey, path); - RLM_SYNC_PARSE_DOUBLE_OR_ABORT(jsonDictionary, kRLMSyncExpiresKey, expires); - return self; - } - return nil; -} - -@end - -@interface RLMTokenModel () - -@property (nonatomic, readwrite) NSString *token; -@property (nonatomic, nullable, readwrite) NSString *path; -@property (nonatomic, readwrite) RLMTokenDataModel *tokenData; - -@end - -@implementation RLMTokenModel - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary { - if (self = [super init]) { - RLM_SYNC_PARSE_STRING_OR_ABORT(jsonDictionary, kRLMSyncTokenKey, token); - RLM_SYNC_PARSE_OPTIONAL_STRING(jsonDictionary, kRLMSyncPathKey, path); - RLM_SYNC_PARSE_MODEL_OR_ABORT(jsonDictionary, kRLMSyncTokenDataKey, RLMTokenDataModel, tokenData); - return self; - } - return nil; -} - -@end diff --git a/Example/Pods/Realm/Realm/RLMUpdateChecker.mm b/Example/Pods/Realm/Realm/RLMUpdateChecker.mm deleted file mode 100644 index e282ee8..0000000 --- a/Example/Pods/Realm/Realm/RLMUpdateChecker.mm +++ /dev/null @@ -1,48 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMUpdateChecker.hpp" - -#import "RLMRealm.h" -#import "RLMUtil.hpp" - -#if TARGET_IPHONE_SIMULATOR && !defined(REALM_COCOA_VERSION) -#import "RLMVersion.h" -#endif - -void RLMCheckForUpdates() { -#if TARGET_IPHONE_SIMULATOR - if (getenv("REALM_DISABLE_UPDATE_CHECKER") || RLMIsRunningInPlayground()) { - return; - } - - auto handler = ^(NSData *data, NSURLResponse *response, NSError *error) { - if (error || ((NSHTTPURLResponse *)response).statusCode != 200) { - return; - } - - NSString *latestVersion = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if (![REALM_COCOA_VERSION isEqualToString:latestVersion]) { - NSLog(@"Version %@ of Realm is now available: https://github.com/realm/realm-cocoa/blob/v%@/CHANGELOG.md", latestVersion, latestVersion); - } - }; - - NSString *url = [NSString stringWithFormat:@"https://static.realm.io/update/cocoa?%@", REALM_COCOA_VERSION]; - [[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:url] completionHandler:handler] resume]; -#endif -} diff --git a/Example/Pods/Realm/Realm/RLMUtil.mm b/Example/Pods/Realm/Realm/RLMUtil.mm deleted file mode 100644 index fa77a9d..0000000 --- a/Example/Pods/Realm/Realm/RLMUtil.mm +++ /dev/null @@ -1,387 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMUtil.hpp" - -#import "RLMArray_Private.hpp" -#import "RLMListBase.h" -#import "RLMObjectSchema_Private.hpp" -#import "RLMObjectStore.h" -#import "RLMObject_Private.hpp" -#import "RLMProperty_Private.h" -#import "RLMSchema_Private.h" -#import "RLMSwiftSupport.h" - -#import "shared_realm.hpp" - -#import -#import - -#include -#include - -#if !defined(REALM_COCOA_VERSION) -#import "RLMVersion.h" -#endif - -static inline bool nsnumber_is_like_integer(__unsafe_unretained NSNumber *const obj) -{ - char data_type = [obj objCType][0]; - return data_type == *@encode(bool) || - data_type == *@encode(char) || - data_type == *@encode(short) || - data_type == *@encode(int) || - data_type == *@encode(long) || - data_type == *@encode(long long) || - data_type == *@encode(unsigned short) || - data_type == *@encode(unsigned int) || - data_type == *@encode(unsigned long) || - data_type == *@encode(unsigned long long); -} - -static inline bool nsnumber_is_like_bool(__unsafe_unretained NSNumber *const obj) -{ - // @encode(BOOL) is 'B' on iOS 64 and 'c' - // objcType is always 'c'. Therefore compare to "c". - if ([obj objCType][0] == 'c') { - return true; - } - - if (nsnumber_is_like_integer(obj)) { - int value = [obj intValue]; - return value == 0 || value == 1; - } - - return false; -} - -static inline bool nsnumber_is_like_float(__unsafe_unretained NSNumber *const obj) -{ - char data_type = [obj objCType][0]; - return data_type == *@encode(float) || - data_type == *@encode(short) || - data_type == *@encode(int) || - data_type == *@encode(long) || - data_type == *@encode(long long) || - data_type == *@encode(unsigned short) || - data_type == *@encode(unsigned int) || - data_type == *@encode(unsigned long) || - data_type == *@encode(unsigned long long) || - // A double is like float if it fits within float bounds - (data_type == *@encode(double) && ABS([obj doubleValue]) <= FLT_MAX); -} - -static inline bool nsnumber_is_like_double(__unsafe_unretained NSNumber *const obj) -{ - char data_type = [obj objCType][0]; - return data_type == *@encode(double) || - data_type == *@encode(float) || - data_type == *@encode(short) || - data_type == *@encode(int) || - data_type == *@encode(long) || - data_type == *@encode(long long) || - data_type == *@encode(unsigned short) || - data_type == *@encode(unsigned int) || - data_type == *@encode(unsigned long) || - data_type == *@encode(unsigned long long); -} - -BOOL RLMIsObjectValidForProperty(__unsafe_unretained id const obj, - __unsafe_unretained RLMProperty *const property) { - if (property.optional && !RLMCoerceToNil(obj)) { - return YES; - } - - switch (property.type) { - case RLMPropertyTypeString: - return [obj isKindOfClass:[NSString class]]; - case RLMPropertyTypeBool: - if ([obj isKindOfClass:[NSNumber class]]) { - return nsnumber_is_like_bool(obj); - } - return NO; - case RLMPropertyTypeDate: - return [obj isKindOfClass:[NSDate class]]; - case RLMPropertyTypeInt: - if (NSNumber *number = RLMDynamicCast(obj)) { - return nsnumber_is_like_integer(number); - } - return NO; - case RLMPropertyTypeFloat: - if (NSNumber *number = RLMDynamicCast(obj)) { - return nsnumber_is_like_float(number); - } - return NO; - case RLMPropertyTypeDouble: - if (NSNumber *number = RLMDynamicCast(obj)) { - return nsnumber_is_like_double(number); - } - return NO; - case RLMPropertyTypeData: - return [obj isKindOfClass:[NSData class]]; - case RLMPropertyTypeAny: - return NO; - case RLMPropertyTypeObject: - case RLMPropertyTypeLinkingObjects: { - // only NSNull, nil, or objects which derive from RLMObject and match the given - // object class are valid - RLMObjectBase *objBase = RLMDynamicCast(obj); - return objBase && [objBase->_objectSchema.className isEqualToString:property.objectClassName]; - } - case RLMPropertyTypeArray: { - if (RLMArray *array = RLMDynamicCast(obj)) { - return [array.objectClassName isEqualToString:property.objectClassName]; - } - if (RLMListBase *list = RLMDynamicCast(obj)) { - return [list._rlmArray.objectClassName isEqualToString:property.objectClassName]; - } - if ([obj conformsToProtocol:@protocol(NSFastEnumeration)]) { - // check each element for compliance - for (id el in (id)obj) { - RLMObjectBase *obj = RLMDynamicCast(el); - if (!obj || ![obj->_objectSchema.className isEqualToString:property.objectClassName]) { - return NO; - } - } - return YES; - } - if (!obj || obj == NSNull.null) { - return YES; - } - return NO; - } - } - @throw RLMException(@"Invalid RLMPropertyType specified"); -} - -NSDictionary *RLMDefaultValuesForObjectSchema(__unsafe_unretained RLMObjectSchema *const objectSchema) { - if (!objectSchema.isSwiftClass) { - return [objectSchema.objectClass defaultPropertyValues]; - } - - NSMutableDictionary *defaults = nil; - if ([objectSchema.objectClass isSubclassOfClass:RLMObject.class]) { - defaults = [NSMutableDictionary dictionaryWithDictionary:[objectSchema.objectClass defaultPropertyValues]]; - } - else { - defaults = [NSMutableDictionary dictionary]; - } - RLMObject *defaultObject = [[objectSchema.objectClass alloc] init]; - for (RLMProperty *prop in objectSchema.properties) { - if (!defaults[prop.name] && defaultObject[prop.name]) { - defaults[prop.name] = defaultObject[prop.name]; - } - } - return defaults; -} - -static NSException *RLMException(NSString *reason, NSDictionary *additionalUserInfo) { - NSMutableDictionary *userInfo = @{RLMRealmVersionKey: REALM_COCOA_VERSION, - RLMRealmCoreVersionKey: @REALM_VERSION}.mutableCopy; - if (additionalUserInfo != nil) { - [userInfo addEntriesFromDictionary:additionalUserInfo]; - } - NSException *e = [NSException exceptionWithName:RLMExceptionName - reason:reason - userInfo:userInfo]; - return e; -} - -NSException *RLMException(NSString *fmt, ...) { - va_list args; - va_start(args, fmt); - NSException *e = RLMException([[NSString alloc] initWithFormat:fmt arguments:args], @{}); - va_end(args); - return e; -} - -NSException *RLMException(std::exception const& exception) { - return RLMException(@"%@", @(exception.what())); -} - -NSError *RLMMakeError(RLMError code, std::exception const& exception) { - return [NSError errorWithDomain:RLMErrorDomain - code:code - userInfo:@{NSLocalizedDescriptionKey: @(exception.what()), - @"Error Code": @(code)}]; -} - -NSError *RLMMakeError(RLMError code, const realm::util::File::AccessError& exception) { - return [NSError errorWithDomain:RLMErrorDomain - code:code - userInfo:@{NSLocalizedDescriptionKey: @(exception.what()), - NSFilePathErrorKey: @(exception.get_path().c_str()), - @"Error Code": @(code)}]; -} - -NSError *RLMMakeError(RLMError code, const realm::RealmFileException& exception) { - NSString *underlying = @(exception.underlying().c_str()); - return [NSError errorWithDomain:RLMErrorDomain - code:code - userInfo:@{NSLocalizedDescriptionKey: @(exception.what()), - NSFilePathErrorKey: @(exception.path().c_str()), - @"Error Code": @(code), - @"Underlying": underlying.length == 0 ? @"n/a" : underlying}]; -} - -NSError *RLMMakeError(std::system_error const& exception) { - BOOL isGenericCategoryError = (exception.code().category() == std::generic_category()); - NSString *category = @(exception.code().category().name()); - NSString *errorDomain = isGenericCategoryError ? NSPOSIXErrorDomain : RLMUnknownSystemErrorDomain; - - return [NSError errorWithDomain:errorDomain - code:exception.code().value() - userInfo:@{NSLocalizedDescriptionKey: @(exception.what()), - @"Error Code": @(exception.code().value()), - @"Category": category}]; -} - -NSError *RLMMakeError(NSException *exception) { - return [NSError errorWithDomain:RLMErrorDomain - code:0 - userInfo:@{NSLocalizedDescriptionKey: exception.reason}]; -} - -void RLMSetErrorOrThrow(NSError *error, NSError **outError) { - if (outError) { - *outError = error; - } - else { - NSString *msg = error.localizedDescription; - if (error.userInfo[NSFilePathErrorKey]) { - msg = [NSString stringWithFormat:@"%@: %@", error.userInfo[NSFilePathErrorKey], error.localizedDescription]; - } - @throw RLMException(msg, @{NSUnderlyingErrorKey: error}); - } -} - -// Determines if class1 descends from class2 -static inline BOOL RLMIsSubclass(Class class1, Class class2) { - class1 = class_getSuperclass(class1); - return RLMIsKindOfClass(class1, class2); -} - -static bool treatFakeObjectAsRLMObject = false; - -void RLMSetTreatFakeObjectAsRLMObject(BOOL flag) { - treatFakeObjectAsRLMObject = flag; -} - -BOOL RLMIsObjectOrSubclass(Class klass) { - if (RLMIsKindOfClass(klass, RLMObjectBase.class)) { - return YES; - } - - if (treatFakeObjectAsRLMObject) { - static Class FakeObjectClass = NSClassFromString(@"FakeObject"); - return RLMIsKindOfClass(klass, FakeObjectClass); - } - return NO; -} - -BOOL RLMIsObjectSubclass(Class klass) { - if (RLMIsSubclass(class_getSuperclass(klass), RLMObjectBase.class)) { - return YES; - } - - if (treatFakeObjectAsRLMObject) { - static Class FakeObjectClass = NSClassFromString(@"FakeObject"); - return RLMIsSubclass(klass, FakeObjectClass); - } - return NO; -} - -BOOL RLMIsDebuggerAttached() -{ - int name[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - getpid() - }; - - struct kinfo_proc info; - size_t info_size = sizeof(info); - if (sysctl(name, sizeof(name)/sizeof(name[0]), &info, &info_size, NULL, 0) == -1) { - NSLog(@"sysctl() failed: %s", strerror(errno)); - return false; - } - - return (info.kp_proc.p_flag & P_TRACED) != 0; -} - -BOOL RLMIsRunningInPlayground() { - return [[NSBundle mainBundle].bundleIdentifier hasPrefix:@"com.apple.dt.playground."]; -} - -id RLMMixedToObjc(realm::Mixed const& mixed) { - switch (mixed.get_type()) { - case realm::type_String: - return RLMStringDataToNSString(mixed.get_string()); - case realm::type_Int: - return @(mixed.get_int()); - case realm::type_Float: - return @(mixed.get_float()); - case realm::type_Double: - return @(mixed.get_double()); - case realm::type_Bool: - return @(mixed.get_bool()); - case realm::type_Timestamp: - return RLMTimestampToNSDate(mixed.get_timestamp()); - case realm::type_Binary: - return RLMBinaryDataToNSData(mixed.get_binary()); - case realm::type_Link: - case realm::type_LinkList: - default: - @throw RLMException(@"Invalid data type for RLMPropertyTypeAny property."); - } -} - -NSString *RLMDefaultDirectoryForBundleIdentifier(NSString *bundleIdentifier) { -#if TARGET_OS_TV - (void)bundleIdentifier; - // tvOS prohibits writing to the Documents directory, so we use the Library/Caches directory instead. - return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; -#elif TARGET_OS_IPHONE - (void)bundleIdentifier; - // On iOS the Documents directory isn't user-visible, so put files there - return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; -#else - // On OS X it is, so put files in Application Support. If we aren't running - // in a sandbox, put it in a subdirectory based on the bundle identifier - // to avoid accidentally sharing files between applications - NSString *path = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0]; - if (![[NSProcessInfo processInfo] environment][@"APP_SANDBOX_CONTAINER_ID"]) { - if (!bundleIdentifier) { - bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; - } - if (!bundleIdentifier) { - bundleIdentifier = [NSBundle mainBundle].executablePath.lastPathComponent; - } - - path = [path stringByAppendingPathComponent:bundleIdentifier]; - - // create directory - [[NSFileManager defaultManager] createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:nil]; - } - return path; -#endif -} diff --git a/Example/Pods/Realm/Realm/module.modulemap b/Example/Pods/Realm/Realm/module.modulemap deleted file mode 100644 index ef2d102..0000000 --- a/Example/Pods/Realm/Realm/module.modulemap +++ /dev/null @@ -1,29 +0,0 @@ -framework module Realm { - umbrella header "Realm.h" - - export * - module * { export * } - - explicit module Private { - header "RLMAccessor.h" - header "RLMArray_Private.h" - header "RLMListBase.h" - header "RLMObjectBase_Dynamic.h" - header "RLMObjectSchema_Private.h" - header "RLMObjectStore.h" - header "RLMObject_Private.h" - header "RLMOptionalBase.h" - header "RLMProperty_Private.h" - header "RLMRealmConfiguration_Private.h" - header "RLMRealm_Private.h" - header "RLMResults_Private.h" - header "RLMSchema_Private.h" - header "RLMSyncConfiguration_Private.h" - header "RLMSyncUtil_Private.h" - } - - explicit module Dynamic { - header "RLMRealm_Dynamic.h" - header "RLMObjectBase_Dynamic.h" - } -} diff --git a/Example/Pods/Realm/build.sh b/Example/Pods/Realm/build.sh deleted file mode 100755 index 5008d00..0000000 --- a/Example/Pods/Realm/build.sh +++ /dev/null @@ -1,1402 +0,0 @@ -#!/bin/sh - -################################################################################## -# Custom build tool for Realm Objective-C binding. -# -# (C) Copyright 2011-2015 by realm.io. -################################################################################## - -# Warning: pipefail is not a POSIX compatible option, but on OS X it works just fine. -# OS X uses a POSIX complain version of bash as /bin/sh, but apparently it does -# not strip away this feature. Also, this will fail if somebody forces the script -# to be run with zsh. -set -o pipefail -set -e - -source_root="$(dirname "$0")" - -# You can override the version of the core library -: ${REALM_CORE_VERSION:=$(sed -n 's/^REALM_CORE_VERSION=\(.*\)$/\1/p' ${source_root}/dependencies.list)} # set to "current" to always use the current build - -: ${REALM_SYNC_VERSION:=$(sed -n 's/^REALM_SYNC_VERSION=\(.*\)$/\1/p' ${source_root}/dependencies.list)} - -: ${REALM_OBJECT_SERVER_VERSION:=$(sed -n 's/^REALM_OBJECT_SERVER_VERSION=\(.*\)$/\1/p' ${source_root}/dependencies.list)} - -# You can override the xcmode used -: ${XCMODE:=xcodebuild} # must be one of: xcodebuild (default), xcpretty, xctool - -# Provide a fallback value for TMPDIR, relevant for Xcode Bots -: ${TMPDIR:=$(getconf DARWIN_USER_TEMP_DIR)} - -PATH=/usr/libexec:$PATH - -if ! [ -z "${JENKINS_HOME}" ]; then - XCPRETTY_PARAMS="--no-utf --report junit --output build/reports/junit.xml" - CODESIGN_PARAMS="CODE_SIGN_IDENTITY= CODE_SIGNING_REQUIRED=NO" -fi - -usage() { -cat </dev/null - done -} - -download_object_server() { - local archive_name="realm-object-server-bundled_node_darwin-developer-$REALM_OBJECT_SERVER_VERSION.tar.gz" - curl -L -O "https://static.realm.io/downloads/object-server/$archive_name" - rm -rf sync - mkdir sync - tar xf $archive_name -C sync - rm $archive_name - cp Configuration/object-server-config.yml sync/object-server/configuration.yml - touch "sync/object-server/do_not_open_browser" -} - -download_core() { - echo "Downloading dependency: core ${REALM_CORE_VERSION}" - TMP_DIR="$TMPDIR/core_bin" - mkdir -p "${TMP_DIR}" - CORE_TMP_TAR="${TMP_DIR}/core-${REALM_CORE_VERSION}.tar.xz.tmp" - CORE_TAR="${TMP_DIR}/core-${REALM_CORE_VERSION}.tar.xz" - if [ ! -f "${CORE_TAR}" ]; then - local CORE_URL="https://static.realm.io/downloads/core/realm-core-${REALM_CORE_VERSION}.tar.xz" - set +e # temporarily disable immediate exit - local ERROR # sweeps the exit code unless declared separately - ERROR=$(curl --fail --silent --show-error --location "$CORE_URL" --output "${CORE_TMP_TAR}" 2>&1 >/dev/null) - if [[ $? -ne 0 ]]; then - echo "Downloading core failed:\n${ERROR}" - exit 1 - fi - set -e # re-enable flag - mv "${CORE_TMP_TAR}" "${CORE_TAR}" - fi - - ( - cd "${TMP_DIR}" - rm -rf core - tar xf "${CORE_TAR}" --xz - mv core core-${REALM_CORE_VERSION} - ) - - rm -rf core-${REALM_CORE_VERSION} core - mv ${TMP_DIR}/core-${REALM_CORE_VERSION} . - ln -s core-${REALM_CORE_VERSION} core -} - -download_sync() { - echo "Downloading dependency: sync ${REALM_SYNC_VERSION}" - TMP_DIR="$TMPDIR/sync_bin" - mkdir -p "${TMP_DIR}" - SYNC_TMP_TAR="${TMP_DIR}/sync-${REALM_SYNC_VERSION}.tar.xz.tmp" - SYNC_TAR="${TMP_DIR}/sync-${REALM_SYNC_VERSION}.tar.xz" - if [ ! -f "${SYNC_TAR}" ]; then - local SYNC_URL="https://static.realm.io/downloads/sync/realm-sync-cocoa-${REALM_SYNC_VERSION}.tar.xz" - set +e # temporarily disable immediate exit - local ERROR # sweeps the exit code unless declared separately - ERROR=$(curl --fail --silent --show-error --location "$SYNC_URL" --output "${SYNC_TMP_TAR}" 2>&1 >/dev/null) - if [[ $? -ne 0 ]]; then - echo "Downloading sync failed:\n${ERROR}" - exit 1 - fi - set -e # re-enable flag - mv "${SYNC_TMP_TAR}" "${SYNC_TAR}" - fi - - ( - cd "${TMP_DIR}" - rm -rf sync - tar xf "${SYNC_TAR}" --xz - mv core sync-${REALM_SYNC_VERSION} - ) - - rm -rf sync-${REALM_SYNC_VERSION} core - mv ${TMP_DIR}/sync-${REALM_SYNC_VERSION} . - ln -s sync-${REALM_SYNC_VERSION} core -} - -###################################### -# Variables -###################################### - -COMMAND="$1" - -# Use Debug config if command ends with -debug, otherwise default to Release -case "$COMMAND" in - *-debug) - COMMAND="${COMMAND%-debug}" - CONFIGURATION="Debug" - ;; - *) CONFIGURATION=${CONFIGURATION:-Release} -esac -export CONFIGURATION - -source "${source_root}/scripts/swift-version.sh" - -case "$COMMAND" in - - ###################################### - # Clean - ###################################### - "clean") - find . -type d -name build -exec rm -r "{}" +\; - exit 0 - ;; - - ###################################### - # Object Server - ###################################### - "download-object-server") - download_object_server - exit 0 - ;; - - "start-object-server") - kill_object_server - ./sync/start-object-server.command - exit 0 - ;; - - "reset-object-server-between-tests") - # Leave the server files alone to avoid 'bad_server_ident' errors - rm -rf "~/Library/Application Support/xctest" - rm -rf "~/Library/Application Support/io.realm.TestHost" - rm -rf "~/Library/Application Support/xctest-child" - exit 0 - ;; - - "reset-object-server") - kill_object_server - # Add a short delay, so file system doesn't complain about files in use - sleep 1 - package="${source_root}/sync" - for file in "$package"/realm-object-server-*; do - if [ -d "$file" ]; then - package="$file" - break - fi - done - rm -rf "$package/object-server/root_dir/" - rm -rf "$package/object-server/temp_dir/" - sh build.sh reset-object-server-between-tests - exit 0 - ;; - - ###################################### - # Core - ###################################### - "download-core") - if [ "$REALM_CORE_VERSION" = "current" ]; then - echo "Using version of core already in core/ directory" - exit 0 - fi - if [ -d core -a -d ../realm-core -a ! -L core ]; then - # Allow newer versions than expected for local builds as testing - # with unreleased versions is one of the reasons to use a local build - if ! $(grep -i "${REALM_CORE_VERSION} Release notes" core/release_notes.txt >/dev/null); then - echo "Local build of core is out of date." - exit 1 - else - echo "The core library seems to be up to date." - fi - elif ! [ -L core ]; then - echo "core is not a symlink. Deleting..." - rm -rf core - download_core - # With a prebuilt version we only want to check the first non-empty - # line so that checking out an older commit will download the - # appropriate version of core if the already-present version is too new - elif ! $(grep -m 1 . core/release_notes.txt | grep -i "${REALM_CORE_VERSION} RELEASE NOTES" >/dev/null); then - download_core - else - echo "The core library seems to be up to date." - fi - exit 0 - ;; - - ###################################### - # Sync - ###################################### - "download-sync") - if [ "$REALM_SYNC_VERSION" = "current" ]; then - echo "Using version of core already in core/ directory" - exit 0 - fi - if [ -d core -a -d ../realm-core -a -d ../realm-sync -a ! -L core ]; then - echo "Using version of core already in core/ directory" - elif ! [ -L core ]; then - echo "core is not a symlink. Deleting..." - rm -rf core - download_sync - elif [[ "$(cat core/version.txt)" != "$REALM_SYNC_VERSION" ]]; then - download_sync - else - echo "The core library seems to be up to date." - fi - exit 0 - ;; - - ###################################### - # Swift versioning - ###################################### - "set-swift-version") - version="$2" - if [[ -z "$version" ]]; then - version="$REALM_SWIFT_VERSION" - fi - - SWIFT_VERSION_FILE="RealmSwift/SwiftVersion.swift" - CONTENTS="let swiftLanguageVersion = \"$version\"" - if [ ! -f "$SWIFT_VERSION_FILE" ] || ! grep -q "$CONTENTS" "$SWIFT_VERSION_FILE"; then - echo "$CONTENTS" > "$SWIFT_VERSION_FILE" - fi - - exit 0 - ;; - - "prelaunch-simulator") - sh ${source_root}/scripts/reset-simulators.sh - ;; - - ###################################### - # Building - ###################################### - "build") - sh build.sh ios-static - sh build.sh ios-dynamic - sh build.sh ios-swift - sh build.sh watchos - sh build.sh watchos-swift - sh build.sh tvos - sh build.sh tvos-swift - sh build.sh osx - sh build.sh osx-swift - exit 0 - ;; - - "ios-static") - build_combined 'Realm iOS static' Realm iphoneos iphonesimulator "-static" - exit 0 - ;; - - "ios-dynamic") - build_combined Realm Realm iphoneos iphonesimulator - exit 0 - ;; - - "ios-swift") - sh build.sh ios-dynamic - build_combined RealmSwift RealmSwift iphoneos iphonesimulator '' "/swift-$REALM_SWIFT_VERSION" - cp -R build/ios/Realm.framework build/ios/swift-$REALM_SWIFT_VERSION - exit 0 - ;; - - "watchos") - build_combined Realm Realm watchos watchsimulator - exit 0 - ;; - - "watchos-swift") - sh build.sh watchos - build_combined RealmSwift RealmSwift watchos watchsimulator '' "/swift-$REALM_SWIFT_VERSION" - cp -R build/watchos/Realm.framework build/watchos/swift-$REALM_SWIFT_VERSION - exit 0 - ;; - - "tvos") - build_combined Realm Realm appletvos appletvsimulator - exit 0 - ;; - - "tvos-swift") - sh build.sh tvos - build_combined RealmSwift RealmSwift appletvos appletvsimulator '' "/swift-$REALM_SWIFT_VERSION" - cp -R build/tvos/Realm.framework build/tvos/swift-$REALM_SWIFT_VERSION - exit 0 - ;; - - "osx") - xc "-scheme Realm -configuration $CONFIGURATION" - clean_retrieve "build/DerivedData/Realm/Build/Products/$CONFIGURATION/Realm.framework" "build/osx" "Realm.framework" - exit 0 - ;; - - "osx-swift") - sh build.sh osx - xc "-scheme 'RealmSwift' -configuration $CONFIGURATION build" - destination="build/osx/swift-$REALM_SWIFT_VERSION" - clean_retrieve "build/DerivedData/Realm/Build/Products/$CONFIGURATION/RealmSwift.framework" "$destination" "RealmSwift.framework" - cp -R build/osx/Realm.framework "$destination" - exit 0 - ;; - - ###################################### - # Analysis - ###################################### - - "analyze-osx") - xc "-scheme Realm -configuration $CONFIGURATION analyze" - exit 0 - ;; - - ###################################### - # Testing - ###################################### - "test") - set +e # Run both sets of tests even if the first fails - failed=0 - sh build.sh test-ios-static || failed=1 - sh build.sh test-ios-dynamic || failed=1 - sh build.sh test-ios-swift || failed=1 - sh build.sh test-ios-devices || failed=1 - sh build.sh test-tvos-devices || failed=1 - sh build.sh test-osx || failed=1 - sh build.sh test-osx-swift || failed=1 - exit $failed - ;; - - "test-all") - set +e - failed=0 - sh build.sh test || failed=1 - sh build.sh test-debug || failed=1 - exit $failed - ;; - - "test-ios-static") - test_ios_static "name=iPhone 6" - exit 0 - ;; - - "test-ios7-static") - test_ios_static "name=iPhone 5S,OS=7.1" - exit 0 - ;; - - "test-ios-dynamic") - xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build" - xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'" - xc "-scheme Realm -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test" - exit 0 - ;; - - "test-ios-swift") - xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' build" - xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test 'ARCHS=\$(ARCHS_STANDARD_32_BIT)'" - xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk iphonesimulator -destination 'name=iPhone 6' test" - exit 0 - ;; - - "test-ios-devices") - failed=0 - trap "failed=1" ERR - sh build.sh test-ios-devices-objc - sh build.sh test-ios-devices-swift - exit $failed - ;; - - "test-ios-devices-objc") - test_devices iphoneos "Realm" "$CONFIGURATION" - exit $? - ;; - - "test-ios-devices-swift") - test_devices iphoneos "RealmSwift" "$CONFIGURATION" - exit $? - ;; - - "test-tvos") - xc "-scheme Realm -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=Apple TV 1080p' test" - exit $? - ;; - - "test-tvos-swift") - xc "-scheme RealmSwift -configuration $CONFIGURATION -sdk appletvsimulator -destination 'name=Apple TV 1080p' test" - exit $? - ;; - - "test-tvos-devices") - test_devices appletvos TestHost "$CONFIGURATION" - ;; - - "test-osx") - COVERAGE_PARAMS="" - if [[ "$CONFIGURATION" == "Debug" ]]; then - COVERAGE_PARAMS="GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES" - fi - xc "-scheme Realm -configuration $CONFIGURATION test $COVERAGE_PARAMS" - exit 0 - ;; - - "test-osx-swift") - xc "-scheme RealmSwift -configuration $CONFIGURATION test" - exit 0 - ;; - - "test-osx-object-server") - xc "-scheme 'Object Server Tests' -configuration $CONFIGURATION -sdk macosx test" - exit 0 - ;; - - ###################################### - # Full verification - ###################################### - "verify") - sh build.sh verify-cocoapods - sh build.sh verify-docs - sh build.sh verify-osx - sh build.sh verify-osx-debug - sh build.sh verify-osx-swift - sh build.sh verify-osx-swift-debug - sh build.sh verify-ios-static - sh build.sh verify-ios-static-debug - sh build.sh verify-ios7-static - sh build.sh verify-ios7-static-debug - sh build.sh verify-ios-dynamic - sh build.sh verify-ios-dynamic-debug - sh build.sh verify-ios-swift - sh build.sh verify-ios-swift-debug - sh build.sh verify-ios-device-objc - sh build.sh verify-ios-device-swift - sh build.sh verify-watchos - sh build.sh verify-tvos - sh build.sh verify-tvos-debug - sh build.sh verify-tvos-device - sh build.sh verify-swiftlint - sh build.sh verify-osx-object-server - ;; - - "verify-cocoapods") - if [[ -d .git ]]; then - # Verify the current branch, unless one was already specified in the sha environment variable. - if [[ -z $sha ]]; then - export sha=$(git rev-parse --abbrev-ref HEAD) - fi - - if [[ $(git log -1 @{push}..) != "" ]] || ! git diff-index --quiet HEAD; then - echo "WARNING: verify-cocoapods will test the latest revision of $sha found on GitHub." - echo " Any unpushed local changes will not be tested." - echo "" - sleep 1 - fi - fi - - cd examples/installation - sh build.sh test-ios-objc-cocoapods - sh build.sh test-ios-objc-cocoapods-dynamic - sh build.sh test-ios-swift-cocoapods - sh build.sh test-osx-objc-cocoapods - sh build.sh test-osx-swift-cocoapods - sh build.sh test-watchos-objc-cocoapods - sh build.sh test-watchos-swift-cocoapods - ;; - - "verify-osx-encryption") - REALM_ENCRYPT_ALL=YES sh build.sh test-osx - exit 0 - ;; - - "verify-osx") - sh build.sh test-osx - sh build.sh analyze-osx - sh build.sh examples-osx - - ( - cd examples/osx/objc/build/DerivedData/RealmExamples/Build/Products/$CONFIGURATION - DYLD_FRAMEWORK_PATH=. ./JSONImport >/dev/null - ) - exit 0 - ;; - - "verify-osx-swift") - sh build.sh test-osx-swift - exit 0 - ;; - - "verify-ios-static") - sh build.sh test-ios-static - sh build.sh examples-ios - ;; - - "verify-ios7-static") - sh build.sh test-ios7-static - ;; - - "verify-ios-dynamic") - sh build.sh test-ios-dynamic - ;; - - "verify-ios-swift") - sh build.sh test-ios-swift - sh build.sh examples-ios-swift - ;; - - "verify-ios-device-objc") - sh build.sh test-ios-devices-objc - exit 0 - ;; - - "verify-ios-device-swift") - sh build.sh test-ios-devices-swift - exit 0 - ;; - - "verify-docs") - sh build.sh docs - for lang in swift objc; do - undocumented="docs/${lang}_output/undocumented.json" - if ruby -rjson -e "j = JSON.parse(File.read('docs/${lang}_output/undocumented.json')); exit j['warnings'].length != 0"; then - echo "Undocumented Realm $lang declarations:" - cat "$undocumented" - exit 1 - fi - done - exit 0 - ;; - - "verify-watchos") - sh build.sh watchos-swift - exit 0 - ;; - - "verify-tvos") - sh build.sh test-tvos - sh build.sh test-tvos-swift - sh build.sh examples-tvos - sh build.sh examples-tvos-swift - exit 0 - ;; - - "verify-tvos-device") - sh build.sh test-tvos-devices - exit 0 - ;; - - "verify-swiftlint") - swiftlint lint --strict - exit 0 - ;; - - "verify-osx-object-server") - sh build.sh download-object-server - sh build.sh test-osx-object-server - sh build.sh reset-object-server - exit 0 - ;; - - ###################################### - # Docs - ###################################### - "docs") - build_docs objc - build_docs swift - exit 0 - ;; - - ###################################### - # Examples - ###################################### - "examples") - sh build.sh clean - sh build.sh examples-ios - sh build.sh examples-ios-swift - sh build.sh examples-osx - sh build.sh examples-tvos - sh build.sh examples-tvos-swift - exit 0 - ;; - - "examples-ios") - sh build.sh prelaunch-simulator - workspace="examples/ios/objc/RealmExamples.xcworkspace" - pod install --project-directory="$workspace/.." --no-repo-update - xc "-workspace $workspace -scheme Simple -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme TableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Migration -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Backlink -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme GroupedTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme RACTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Encryption -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Draw -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - - if [ ! -z "${JENKINS_HOME}" ]; then - xc "-workspace $workspace -scheme Extension -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - fi - - exit 0 - ;; - - "examples-ios-swift") - if [ "$REALM_SWIFT_VERSION" == "2.3" ]; then # Skip Swift 2.3 examples for now. - exit 0 - fi - sh build.sh prelaunch-simulator - workspace="examples/ios/swift-$REALM_SWIFT_VERSION/RealmExamples.xcworkspace" - xc "-workspace $workspace -scheme Simple -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme TableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Migration -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Encryption -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme Backlink -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme GroupedTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - if [ "$REALM_SWIFT_VERSION" == "2.2" ]; then # Only Swift 2.2 has the ReactKitTableView example - pod install --project-directory="$workspace/.." --no-repo-update - xc "-workspace $workspace -scheme ReactKitTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" - fi - exit 0 - ;; - - "examples-osx") - xc "-workspace examples/osx/objc/RealmExamples.xcworkspace -scheme JSONImport -configuration ${CONFIGURATION} build ${CODESIGN_PARAMS}" - ;; - - "examples-tvos") - workspace="examples/tvos/objc/RealmExamples.xcworkspace" - xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=Apple TV 1080p' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=Apple TV 1080p' build ${CODESIGN_PARAMS}" - exit 0 - ;; - - "examples-tvos-swift") - if [ "$REALM_SWIFT_VERSION" == "2.3" ]; then # Skip Swift 2.3 examples for now. - exit 0 - fi - workspace="examples/tvos/swift-$REALM_SWIFT_VERSION/RealmExamples.xcworkspace" - xc "-workspace $workspace -scheme DownloadCache -configuration $CONFIGURATION -destination 'name=Apple TV 1080p' build ${CODESIGN_PARAMS}" - xc "-workspace $workspace -scheme PreloadedData -configuration $CONFIGURATION -destination 'name=Apple TV 1080p' build ${CODESIGN_PARAMS}" - exit 0 - ;; - - ###################################### - # Versioning - ###################################### - "get-version") - version_file="Realm/Realm-Info.plist" - echo "$(PlistBuddy -c "Print :CFBundleVersion" "$version_file")" - exit 0 - ;; - - "set-version") - realm_version="$2" - version_files="Realm/Realm-Info.plist" - - if [ -z "$realm_version" ]; then - echo "You must specify a version." - exit 1 - fi - for version_file in $version_files; do - PlistBuddy -c "Set :CFBundleVersion $realm_version" "$version_file" - PlistBuddy -c "Set :CFBundleShortVersionString $realm_version" "$version_file" - done - sed -i '' "s/^VERSION=.*/VERSION=$realm_version/" dependencies.list - exit 0 - ;; - - ###################################### - # Bitcode Detection - ###################################### - - "binary-has-bitcode") - BINARY="$2" - # Although grep has a '-q' flag to prevent logging to stdout, grep - # behaves differently when used, so redirect stdout to /dev/null. - if otool -l "$BINARY" | grep "segname __LLVM" > /dev/null 2>&1; then - exit 0 - fi - # Work around rdar://21826157 by checking for bitcode in thin binaries - - # Get architectures for binary - archs="$(lipo -info "$BINARY" | rev | cut -d ':' -f1 | rev)" - - archs_array=( $archs ) - if [[ ${#archs_array[@]} < 2 ]]; then - exit 1 # Early exit if not a fat binary - fi - - TEMPDIR=$(mktemp -d $TMPDIR/realm-bitcode-check.XXXX) - - for arch in $archs; do - lipo -thin "$arch" "$BINARY" -output "$TEMPDIR/$arch" - if otool -l "$TEMPDIR/$arch" | grep -q "segname __LLVM"; then - exit 0 - fi - done - exit 1 - ;; - - ###################################### - # CocoaPods - ###################################### - "cocoapods-setup") - if [ ! -d core ]; then - sh build.sh download-sync - rm core - mv sync-* core - fi - - if [[ "$2" != "swift" ]]; then - if [ ! -d Realm/ObjectStore/src ]; then - cat >&2 <&1 | tee build/build.log | xcpretty -r junit -o build/reports/junit.xml || failed=1 - if [ "$failed" = "1" ] && cat build/build.log | grep -E 'DTXProxyChannel|DTXChannel|out of date and needs to be rebuilt|operation never finished bootstrapping'; then - echo "Known Xcode error detected. Running job again." - failed=0 - sh build.sh verify-$target | tee build/build.log | xcpretty -r junit -o build/reports/junit.xml || failed=1 - elif [ "$failed" = "1" ] && tail ~/Library/Logs/CoreSimulator/CoreSimulator.log | grep -E "Operation not supported|Failed to lookup com.apple.coreservices.lsuseractivity.simulatorsupport"; then - echo "Known Xcode error detected. Running job again." - failed=0 - sh build.sh verify-$target | tee build/build.log | xcpretty -r junit -o build/reports/junit.xml || failed=1 - fi - if [ "$failed" = "1" ]; then - echo "\n\n***\nbuild/build.log\n***\n\n" && cat build/build.log - echo "\n\n***\nCoreSimulator.log\n***\n\n" && tail -n2000 ~/Library/Logs/CoreSimulator/CoreSimulator.log - exit 1 - fi - fi - - if [ "$target" = "osx" ] && [ "$configuration" = "Debug" ]; then - gcovr -r . -f ".*Realm.*" -e ".*Tests.*" -e ".*core.*" --xml > build/reports/coverage-report.xml - WS=$(pwd | sed "s/\//\\\\\//g") - sed -i ".bak" "s/\./${WS}/" build/reports/coverage-report.xml - fi - ;; - - ###################################### - # Release packaging - ###################################### - - "package-examples") - cd tightdb_objc - ./scripts/package_examples.rb - zip --symlinks -r realm-examples.zip examples -x "examples/installation/*" - ;; - - "package-test-examples") - if ! VERSION=$(echo realm-objc-*.zip | grep -o '\d*\.\d*\.\d*-[a-z]*'); then - VERSION=$(echo realm-objc-*.zip | grep -o '\d*\.\d*\.\d*') - fi - OBJC="realm-objc-${VERSION}" - SWIFT="realm-swift-${VERSION}" - unzip ${OBJC}.zip - - cp $0 ${OBJC} - cp -r ${source_root}/scripts ${OBJC} - cd ${OBJC} - sh build.sh examples-ios - sh build.sh examples-tvos - sh build.sh examples-osx - cd .. - rm -rf ${OBJC} - - unzip ${SWIFT}.zip - - cp $0 ${SWIFT} - cp -r ${source_root}/scripts ${SWIFT} - cd ${SWIFT} - sh build.sh examples-ios-swift - sh build.sh examples-tvos-swift - cd .. - rm -rf ${SWIFT} - ;; - - "package-ios-static") - cd tightdb_objc - - sh build.sh prelaunch-simulator - sh build.sh test-ios-static - sh build.sh ios-static - - cd build/ios-static - zip --symlinks -r realm-framework-ios.zip Realm.framework - ;; - - "package-ios-dynamic") - cd tightdb_objc - - sh build.sh prelaunch-simulator - sh build.sh ios-dynamic - cd build/ios - zip --symlinks -r realm-dynamic-framework-ios.zip Realm.framework - ;; - - "package-osx") - cd tightdb_objc - sh build.sh test-osx - - cd build/DerivedData/Realm/Build/Products/Release - zip --symlinks -r realm-framework-osx.zip Realm.framework - ;; - - "package-ios-swift") - cd tightdb_objc - for version in 2.2 2.3 3.0 3.0.1 3.0.2; do - REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator - REALM_SWIFT_VERSION="$version" sh build.sh ios-swift - done - - cd build/ios - zip --symlinks -r realm-swift-framework-ios.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 swift-3.0.2 - ;; - - "package-osx-swift") - cd tightdb_objc - for version in 2.2 2.3 3.0 3.0.1 3.0.2; do - REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator - REALM_SWIFT_VERSION="$version" sh build.sh osx-swift - done - - cd build/osx - zip --symlinks -r realm-swift-framework-osx.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 swift-3.0.2 - ;; - - "package-watchos") - cd tightdb_objc - sh build.sh watchos - - cd build/watchos - zip --symlinks -r realm-framework-watchos.zip Realm.framework - ;; - - "package-watchos-swift") - cd tightdb_objc - for version in 2.2 2.3 3.0 3.0.1 3.0.2; do - REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator - REALM_SWIFT_VERSION="$version" sh build.sh watchos-swift - done - - cd build/watchos - zip --symlinks -r realm-swift-framework-watchos.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 swift-3.0.2 - ;; - - "package-tvos") - cd tightdb_objc - sh build.sh tvos - - cd build/tvos - zip --symlinks -r realm-framework-tvos.zip Realm.framework - ;; - - "package-tvos-swift") - cd tightdb_objc - for version in 2.2 2.3 3.0 3.0.1 3.0.2; do - REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator - REALM_SWIFT_VERSION="$version" sh build.sh tvos-swift - done - - cd build/tvos - zip --symlinks -r realm-swift-framework-tvos.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 swift-3.0.2 - ;; - - "package-release") - LANG="$2" - TEMPDIR=$(mktemp -d $TMPDIR/realm-release-package-${LANG}.XXXX) - - cd tightdb_objc - VERSION=$(sh build.sh get-version) - cd .. - - FOLDER=${TEMPDIR}/realm-${LANG}-${VERSION} - - mkdir -p ${FOLDER}/osx ${FOLDER}/ios ${FOLDER}/watchos ${FOLDER}/tvos - - if [[ "${LANG}" == "objc" ]]; then - mkdir -p ${FOLDER}/ios/static - mkdir -p ${FOLDER}/ios/dynamic - mkdir -p ${FOLDER}/Swift - - ( - cd ${FOLDER}/osx - unzip ${WORKSPACE}/realm-framework-osx.zip - ) - - ( - cd ${FOLDER}/ios/static - unzip ${WORKSPACE}/realm-framework-ios.zip - ) - - ( - cd ${FOLDER}/ios/dynamic - unzip ${WORKSPACE}/realm-dynamic-framework-ios.zip - ) - - ( - cd ${FOLDER}/watchos - unzip ${WORKSPACE}/realm-framework-watchos.zip - ) - - ( - cd ${FOLDER}/tvos - unzip ${WORKSPACE}/realm-framework-tvos.zip - ) - else - ( - cd ${FOLDER}/osx - unzip ${WORKSPACE}/realm-swift-framework-osx.zip - ) - - ( - cd ${FOLDER}/ios - unzip ${WORKSPACE}/realm-swift-framework-ios.zip - ) - - ( - cd ${FOLDER}/watchos - unzip ${WORKSPACE}/realm-swift-framework-watchos.zip - ) - - ( - cd ${FOLDER}/tvos - unzip ${WORKSPACE}/realm-swift-framework-tvos.zip - ) - fi - - ( - cd ${WORKSPACE}/tightdb_objc - cp -R plugin ${FOLDER} - cp LICENSE ${FOLDER}/LICENSE.txt - if [[ "${LANG}" == "objc" ]]; then - cp Realm/Swift/RLMSupport.swift ${FOLDER}/Swift/ - fi - ) - - ( - cd ${FOLDER} - unzip ${WORKSPACE}/realm-examples.zip - cd examples - if [[ "${LANG}" == "objc" ]]; then - rm -rf ios/swift-* tvos/swift-* - else - rm -rf ios/objc ios/rubymotion osx tvos/objc - fi - ) - - cat > ${FOLDER}/docs.webloc < - - - - URL - https://realm.io/docs/${LANG}/${VERSION} - - -EOF - - ( - cd ${TEMPDIR} - zip --symlinks -r realm-${LANG}-${VERSION}.zip realm-${LANG}-${VERSION} - mv realm-${LANG}-${VERSION}.zip ${WORKSPACE} - ) - ;; - - "test-package-release") - # Generate a release package locally for testing purposes - # Real releases should always be done via Jenkins - if [ -z "${WORKSPACE}" ]; then - echo 'WORKSPACE must be set to a directory to assemble the release in' - exit 1 - fi - if [ -d "${WORKSPACE}" ]; then - echo 'WORKSPACE directory should not already exist' - exit 1 - fi - - REALM_SOURCE="$(pwd)" - mkdir -p "$WORKSPACE" - WORKSPACE="$(cd "$WORKSPACE" && pwd)" - export WORKSPACE - cd $WORKSPACE - git clone --recursive $REALM_SOURCE tightdb_objc - - echo 'Packaging iOS' - sh tightdb_objc/build.sh package-ios-static - cp tightdb_objc/build/ios-static/realm-framework-ios.zip . - sh tightdb_objc/build.sh package-ios-dynamic - cp tightdb_objc/build/ios/realm-dynamic-framework-ios.zip . - sh tightdb_objc/build.sh package-ios-swift - cp tightdb_objc/build/ios/realm-swift-framework-ios.zip . - - echo 'Packaging OS X' - sh tightdb_objc/build.sh package-osx - cp tightdb_objc/build/DerivedData/Realm/Build/Products/Release/realm-framework-osx.zip . - sh tightdb_objc/build.sh package-osx-swift - cp tightdb_objc/build/osx/realm-swift-framework-osx.zip . - - echo 'Packaging watchOS' - sh tightdb_objc/build.sh package-watchos - cp tightdb_objc/build/watchos/realm-framework-watchos.zip . - sh tightdb_objc/build.sh package-watchos-swift - cp tightdb_objc/build/watchos/realm-swift-framework-watchos.zip . - - echo 'Packaging tvOS' - sh tightdb_objc/build.sh package-tvos - cp tightdb_objc/build/tvos/realm-framework-tvos.zip . - sh tightdb_objc/build.sh package-tvos-swift - cp tightdb_objc/build/tvos/realm-swift-framework-tvos.zip . - - echo 'Packaging examples' - sh tightdb_objc/build.sh package-examples - cp tightdb_objc/realm-examples.zip . - - echo 'Building final release packages' - sh tightdb_objc/build.sh package-release objc - sh tightdb_objc/build.sh package-release swift - - echo 'Testing packaged examples' - sh tightdb_objc/build.sh package-test-examples - ;; - - "github-release") - if [ -z "${GITHUB_ACCESS_TOKEN}" ]; then - echo 'GITHUB_ACCESS_TOKEN must be set to create GitHub releases' - exit 1 - fi - ./scripts/github_release.rb - ;; - - "add-empty-changelog") - empty_section=$(cat < CHANGELOG.md - echo >> CHANGELOG.md - echo "$changelog" >> CHANGELOG.md - ;; - - *) - echo "Unknown command '$COMMAND'" - usage - exit 1 - ;; -esac diff --git a/Example/Pods/Realm/core/librealm-ios.a b/Example/Pods/Realm/core/librealm-ios.a deleted file mode 100644 index ca97d70..0000000 Binary files a/Example/Pods/Realm/core/librealm-ios.a and /dev/null differ diff --git a/Example/Pods/Realm/include/RLMAccessor.h b/Example/Pods/Realm/include/RLMAccessor.h deleted file mode 100644 index f70039b..0000000 --- a/Example/Pods/Realm/include/RLMAccessor.h +++ /dev/null @@ -1,63 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - - -@class RLMObjectSchema, RLMProperty, RLMObjectBase, RLMProperty; - -#ifdef __cplusplus -typedef NSUInteger RLMCreationOptions; -#else -typedef NS_OPTIONS(NSUInteger, RLMCreationOptions); -#endif - -NS_ASSUME_NONNULL_BEGIN - -// -// Accessors Class Creation/Caching -// - -// get accessor classes for an object class - generates classes if not cached -Class RLMAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema, NSString *prefix); -Class RLMUnmanagedAccessorClassForObjectClass(Class objectClass, RLMObjectSchema *schema); - -// Check if a given class is a generated accessor class -bool RLMIsGeneratedClass(Class cls); - -// -// Dynamic getters/setters -// -FOUNDATION_EXTERN void RLMDynamicValidatedSet(RLMObjectBase *obj, NSString *propName, id __nullable val); -FOUNDATION_EXTERN id __nullable RLMDynamicGet(RLMObjectBase *obj, RLMProperty *prop); -FOUNDATION_EXTERN id __nullable RLMDynamicGetByName(RLMObjectBase *obj, NSString *propName, bool asList); - -// by property/column -void RLMDynamicSet(RLMObjectBase *obj, RLMProperty *prop, id val, RLMCreationOptions options); - -// -// Class modification -// - -// Replace className method for the given class -void RLMReplaceClassNameMethod(Class accessorClass, NSString *className); - -// Replace sharedSchema method for the given class -void RLMReplaceSharedSchemaMethod(Class accessorClass, RLMObjectSchema * __nullable schema); - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMAnalytics.hpp b/Example/Pods/Realm/include/RLMAnalytics.hpp deleted file mode 100644 index 76bc429..0000000 --- a/Example/Pods/Realm/include/RLMAnalytics.hpp +++ /dev/null @@ -1,55 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -// Asynchronously submits build information to Realm if running in an iOS -// simulator or on OS X if a debugger is attached. Does nothing if running on an -// iOS / watchOS device or if a debugger is *not* attached. -// -// To be clear: this does *not* run when your app is in production or on -// your end-user’s devices; it will only run in the simulator or when a debugger -// is attached. -// -// Why are we doing this? In short, because it helps us build a better product -// for you. None of the data personally identifies you, your employer or your -// app, but it *will* help us understand what language you use, what iOS -// versions you target, etc. Having this info will help prioritizing our time, -// adding new features and deprecating old features. Collecting an anonymized -// bundle & anonymized MAC is the only way for us to count actual usage of the -// other metrics accurately. If we don’t have a way to deduplicate the info -// reported, it will be useless, as a single developer building their Swift app -// 10 times would report 10 times more than a single Objective-C developer that -// only builds once, making the data all but useless. -// No one likes sharing data unless it’s necessary, we get it, and we’ve -// debated adding this for a long long time. Since Realm is a free product -// without an email signup, we feel this is a necessary step so we can collect -// relevant data to build a better product for you. If you truly, absolutely -// feel compelled to not send this data back to Realm, then you can set an env -// variable named REALM_DISABLE_ANALYTICS. Since Realm is free we believe -// letting these analytics run is a small price to pay for the product & support -// we give you. -// -// Currently the following information is reported: -// - What version of Realm is being used, and from which language (obj-c or Swift). -// - What version of OS X it's running on (in case Xcode aggressively drops -// support for older versions again, we need to know what we need to support). -// - The minimum iOS/OS X version that the application is targeting (again, to -// help us decide what versions we need to support). -// - An anonymous MAC address and bundle ID to aggregate the other information on. -// - What version of Swift is being used (if applicable). - -void RLMSendAnalytics(); diff --git a/Example/Pods/Realm/include/RLMArray.h b/Example/Pods/Realm/include/RLMArray.h deleted file mode 100644 index eed53cc..0000000 --- a/Example/Pods/Realm/include/RLMArray.h +++ /dev/null @@ -1,369 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class RLMObject, RLMRealm, RLMResults, RLMNotificationToken; - -/** - `RLMArray` is the container type in Realm used to define to-many relationships. - - Unlike an `NSArray`, `RLMArray`s hold a single type, specified by the `objectClassName` property. - This is referred to in these docs as the “type” of the array. - - When declaring an `RLMArray` property, the type must be marked as conforming to a - protocol by the same name as the objects it should contain (see the - `RLM_ARRAY_TYPE` macro). In addition, the property can be declared using Objective-C - generics for better compile-time type safety. - - RLM_ARRAY_TYPE(ObjectType) - ... - @property RLMArray *arrayOfObjectTypes; - - `RLMArray`s can be queried with the same predicates as `RLMObject` and `RLMResult`s. - - `RLMArray`s cannot be created directly. `RLMArray` properties on `RLMObject`s are - lazily created when accessed, or can be obtained by querying a Realm. - - ### Key-Value Observing - - `RLMArray` supports array key-value observing on `RLMArray` properties on `RLMObject` - subclasses, and the `invalidated` property on `RLMArray` instances themselves is - key-value observing compliant when the `RLMArray` is attached to a managed - `RLMObject` (`RLMArray`s on unmanaged `RLMObject`s will never become invalidated). - - Because `RLMArray`s are attached to the object which they are a property of, they - do not require using the mutable collection proxy objects from - `-mutableArrayValueForKey:` or KVC-compatible mutation methods on the containing - object. Instead, you can call the mutation methods on the `RLMArray` directly. - */ - -@interface RLMArray : NSObject - -#pragma mark - Properties - -/** - The number of objects in the array. - */ -@property (nonatomic, readonly, assign) NSUInteger count; - -/** - The class name (i.e. type) of the `RLMObject`s contained in the array. - */ -@property (nonatomic, readonly, copy) NSString *objectClassName; - -/** - The Realm which manages the array. Returns `nil` for unmanaged arrays. - */ -@property (nonatomic, readonly, nullable) RLMRealm *realm; - -/** - Indicates if the array can no longer be accessed. - */ -@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated; - -#pragma mark - Accessing Objects from an Array - -/** - Returns the object at the index specified. - - @param index The index to look up. - - @return An `RLMObject` of the type contained in the array. - */ -- (RLMObjectType)objectAtIndex:(NSUInteger)index; - -/** - Returns the first object in the array. - - Returns `nil` if called on an empty array. - - @return An `RLMObject` of the type contained in the array. - */ -- (nullable RLMObjectType)firstObject; - -/** - Returns the last object in the array. - - Returns `nil` if called on an empty array. - - @return An `RLMObject` of the type contained in the array. - */ -- (nullable RLMObjectType)lastObject; - - - -#pragma mark - Adding, Removing, and Replacing Objects in an Array - -/** - Adds an object to the end of the array. - - @warning This method may only be called during a write transaction. - - @param object An `RLMObject` of the type contained in the array. - */ -- (void)addObject:(RLMObjectType)object; - -/** - Adds an array of objects to the end of the array. - - @warning This method may only be called during a write transaction. - - @param objects An enumerable object such as `NSArray` or `RLMResults` which contains objects of the - same class as the array. - */ -- (void)addObjects:(id)objects; - -/** - Inserts an object at the given index. - - Throws an exception if the index exceeds the bounds of the array. - - @warning This method may only be called during a write transaction. - - @param anObject An `RLMObject` of the type contained in the array. - @param index The index at which to insert the object. - */ -- (void)insertObject:(RLMObjectType)anObject atIndex:(NSUInteger)index; - -/** - Removes an object at the given index. - - Throws an exception if the index exceeds the bounds of the array. - - @warning This method may only be called during a write transaction. - - @param index The array index identifying the object to be removed. - */ -- (void)removeObjectAtIndex:(NSUInteger)index; - -/** - Removes the last object in the array. - - @warning This method may only be called during a write transaction. -*/ -- (void)removeLastObject; - -/** - Removes all objects from the array. - - @warning This method may only be called during a write transaction. - */ -- (void)removeAllObjects; - -/** - Replaces an object at the given index with a new object. - - Throws an exception if the index exceeds the bounds of the array. - - @warning This method may only be called during a write transaction. - - @param index The index of the object to be replaced. - @param anObject An object (of the same type as returned from the `objectClassName` selector). - */ -- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(RLMObjectType)anObject; - -/** - Moves the object at the given source index to the given destination index. - - Throws an exception if the index exceeds the bounds of the array. - - @warning This method may only be called during a write transaction. - - @param sourceIndex The index of the object to be moved. - @param destinationIndex The index to which the object at `sourceIndex` should be moved. - */ -- (void)moveObjectAtIndex:(NSUInteger)sourceIndex toIndex:(NSUInteger)destinationIndex; - -/** - Exchanges the objects in the array at given indices. - - Throws an exception if either index exceeds the bounds of the array. - - @warning This method may only be called during a write transaction. - - @param index1 The index of the object which should replace the object at index `index2`. - @param index2 The index of the object which should replace the object at index `index1`. - */ -- (void)exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2; - -#pragma mark - Querying an Array - -/** - Returns the index of an object in the array. - - Returns `NSNotFound` if the object is not found in the array. - - @param object An object (of the same type as returned from the `objectClassName` selector). - */ -- (NSUInteger)indexOfObject:(RLMObjectType)object; - -/** - Returns the index of the first object in the array matching the predicate. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return The index of the object, or `NSNotFound` if the object is not found in the array. - */ -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns the index of the first object in the array matching the predicate. - - @param predicate The predicate with which to filter the objects. - - @return The index of the object, or `NSNotFound` if the object is not found in the array. - */ -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate; - -/** - Returns all the objects matching the given predicate in the array. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return An `RLMResults` of objects that match the given predicate. - */ -- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns all the objects matching the given predicate in the array. - - @param predicate The predicate with which to filter the objects. - - @return An `RLMResults` of objects that match the given predicate - */ -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate; - -/** - Returns a sorted `RLMResults` from the array. - - @param property The property name to sort by. - @param ascending The direction to sort in. - - @return An `RLMResults` sorted by the specified property. - */ -- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending; - -/** - Returns a sorted `RLMResults` from the array. - - @param properties An array of `RLMSortDescriptor`s to sort by. - - @return An `RLMResults` sorted by the specified properties. - */ -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; - -/// :nodoc: -- (RLMObjectType)objectAtIndexedSubscript:(NSUInteger)index; - -/// :nodoc: -- (void)setObject:(RLMObjectType)newValue atIndexedSubscript:(NSUInteger)index; - -#pragma mark - Notifications - -/** - Registers a block to be called each time the array changes. - - The block will be asynchronously called with the initial array, and then - called again after each write transaction which changes any of the objects in - the array, which objects are in the results, or the order of the objects in the - array. - - The `changes` parameter will be `nil` the first time the block is called. - For each call after that, it will contain information about - which rows in the array were added, removed or modified. If a write transaction - did not modify any objects in the array, the block is not called at all. - See the `RLMCollectionChange` documentation for information on how the changes - are reported and an example of updating a `UITableView`. - - If an error occurs the block will be called with `nil` for the results - parameter and a non-`nil` error. Currently the only errors that can occur are - when opening the Realm on the background worker thread. - - Notifications are delivered via the standard run loop, and so can't be - delivered while the run loop is blocked by other activity. When - notifications can't be delivered instantly, multiple notifications may be - coalesced into a single notification. This can include the notification - with the initial results. For example, the following code performs a write - transaction immediately after adding the notification block, so there is no - opportunity for the initial notification to be delivered first. As a - result, the initial notification will reflect the state of the Realm after - the write transaction. - - Person *person = [[Person allObjectsInRealm:realm] firstObject]; - NSLog(@"person.dogs.count: %zu", person.dogs.count); // => 0 - self.token = [person.dogs addNotificationBlock(RLMArray *dogs, - RLMCollectionChange *changes, - NSError *error) { - // Only fired once for the example - NSLog(@"dogs.count: %zu", dogs.count) // => 1 - }]; - [realm transactionWithBlock:^{ - Dog *dog = [[Dog alloc] init]; - dog.name = @"Rex"; - [person.dogs addObject:dog]; - }]; - // end of run loop execution context - - You must retain the returned token for as long as you want updates to continue - to be sent to the block. To stop receiving updates, call `-stop` on the token. - - @warning This method cannot be called during a write transaction, or when the - containing Realm is read-only. - @warning This method may only be called on a managed array. - - @param block The block to be called each time the array changes. - @return A token which must be held for as long as you want updates to be delivered. - */ -- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMArray *__nullable array, - RLMCollectionChange *__nullable changes, - NSError *__nullable error))block __attribute__((warn_unused_result)); - -#pragma mark - Unavailable Methods - -/** - `-[RLMArray init]` is not available because `RLMArray`s cannot be created directly. - `RLMArray` properties on `RLMObject`s are lazily created when accessed, or can be obtained by querying a Realm. - */ -- (instancetype)init __attribute__((unavailable("RLMArrays cannot be created directly"))); - -/** - `+[RLMArray new]` is not available because `RLMArray`s cannot be created directly. - `RLMArray` properties on `RLMObject`s are lazily created when accessed, or can be obtained by querying a Realm. - */ -+ (instancetype)new __attribute__((unavailable("RLMArrays cannot be created directly"))); - -@end - -/// :nodoc: -@interface RLMArray (Swift) -// for use only in Swift class definitions -- (instancetype)initWithObjectClassName:(NSString *)objectClassName; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMArray_Private.h b/Example/Pods/Realm/include/RLMArray_Private.h deleted file mode 100644 index 5e15e2d..0000000 --- a/Example/Pods/Realm/include/RLMArray_Private.h +++ /dev/null @@ -1,28 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMArray () -- (instancetype)initWithObjectClassName:(NSString *)objectClassName; -- (NSString *)descriptionWithMaxDepth:(NSUInteger)depth; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMArray_Private.hpp b/Example/Pods/Realm/include/RLMArray_Private.hpp deleted file mode 100644 index 5db9abe..0000000 --- a/Example/Pods/Realm/include/RLMArray_Private.hpp +++ /dev/null @@ -1,70 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMArray_Private.h" - -#import "RLMCollection_Private.hpp" - -#import - -#import - -namespace realm { - class Results; -} - -@class RLMObjectBase, RLMObjectSchema, RLMProperty; -class RLMClassInfo; -class RLMObservationInfo; - -@interface RLMArray () { -@protected - NSString *_objectClassName; -@public - // The name of the property which this RLMArray represents - NSString *_key; - __weak RLMObjectBase *_parentObject; -} -@end - -// -// LinkView backed RLMArray subclass -// -@interface RLMArrayLinkView : RLMArray -- (instancetype)initWithParent:(RLMObjectBase *)parentObject property:(RLMProperty *)property; - -// deletes all objects in the RLMArray from their containing realms -- (void)deleteObjectsFromRealm; -@end - -void RLMValidateArrayObservationKey(NSString *keyPath, RLMArray *array); - -// Initialize the observation info for an array if needed -void RLMEnsureArrayObservationInfo(std::unique_ptr& info, - NSString *keyPath, RLMArray *array, id observed); - - -// -// RLMResults private methods -// -@interface RLMResults () -+ (instancetype)resultsWithObjectInfo:(RLMClassInfo&)info - results:(realm::Results)results; - -- (void)deleteObjectsFromRealm; -@end diff --git a/Example/Pods/Realm/include/RLMAuthResponseModel.h b/Example/Pods/Realm/include/RLMAuthResponseModel.h deleted file mode 100644 index 0cbf68e..0000000 --- a/Example/Pods/Realm/include/RLMAuthResponseModel.h +++ /dev/null @@ -1,52 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -/** - An internal class representing a valid JSON response to an auth request. - - ``` - { - "access_token": { ... } // (optional), - "refresh_token": { ... } // (optional) - } - ``` - */ -@class RLMTokenModel; - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMAuthResponseModel : NSObject - -@property (nonatomic, readonly, nullable) RLMTokenModel *accessToken; -@property (nonatomic, readonly, nullable) RLMTokenModel *refreshToken; - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary - requireAccessToken:(BOOL)requireAccessToken - requireRefreshToken:(BOOL)requireRefreshToken; - -/// :nodoc: -- (instancetype)init __attribute__((unavailable("RLMTokenModel cannot be created directly"))); - -/// :nodoc: -+ (instancetype)new __attribute__((unavailable("RLMTokenModel cannot be created directly"))); - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMClassInfo.hpp b/Example/Pods/Realm/include/RLMClassInfo.hpp deleted file mode 100644 index ea4610a..0000000 --- a/Example/Pods/Realm/include/RLMClassInfo.hpp +++ /dev/null @@ -1,107 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 -#import -#import - -namespace realm { - class ObjectSchema; - class Schema; - class Table; - struct Property; -} - -class RLMObservationInfo; -@class RLMRealm, RLMSchema, RLMObjectSchema, RLMProperty; - -NS_ASSUME_NONNULL_BEGIN - -namespace std { -// Add specializations so that NSString can be used as the key for hash containers -template<> struct hash { - size_t operator()(__unsafe_unretained NSString *const str) const { - return [str hash]; - } -}; -template<> struct equal_to { - bool operator()(__unsafe_unretained NSString * lhs, __unsafe_unretained NSString *rhs) const { - return [lhs isEqualToString:rhs]; - } -}; -} - -// The per-RLMRealm object schema information which stores the cached table -// reference, handles table column lookups, and tracks observed objects -class RLMClassInfo { -public: - RLMClassInfo(RLMRealm *, RLMObjectSchema *, const realm::ObjectSchema *); - - __unsafe_unretained RLMRealm *const realm; - __unsafe_unretained RLMObjectSchema *const rlmObjectSchema; - const realm::ObjectSchema *const objectSchema; - - // Storage for the functionality in RLMObservation for handling indirect - // changes to KVO-observed things - std::vector observedObjects; - - // Get the table for this object type. Will return nullptr only if it's a - // read-only Realm that is missing the table entirely. - realm::Table *_Nullable table() const; - - // Get the RLMProperty for a given table column, or `nil` if it is a column - // not used by the current schema - RLMProperty *_Nullable propertyForTableColumn(NSUInteger) const noexcept; - - // Get the RLMProperty that's used as the primary key, or `nil` if there is - // no primary key for the current schema - RLMProperty *_Nullable propertyForPrimaryKey() const noexcept; - - // Get the table column for the given property. The property must be a valid - // persisted property. - NSUInteger tableColumn(NSString *propertyName) const; - NSUInteger tableColumn(RLMProperty *property) const; - - RLMClassInfo &linkTargetType(size_t index); - - void releaseTable() { m_table = nullptr; } - -private: - mutable realm::Table *_Nullable m_table = nullptr; - std::vector m_linkTargets; -}; - -// A per-RLMRealm object schema map which stores RLMClassInfo keyed on the name -class RLMSchemaInfo { - using impl = std::unordered_map; -public: - RLMSchemaInfo() = default; - RLMSchemaInfo(RLMRealm *realm, RLMSchema *rlmSchema, realm::Schema const& schema); - - // Look up by name, throwing if it's not present - RLMClassInfo& operator[](NSString *name); - - impl::iterator begin() noexcept; - impl::iterator end() noexcept; - impl::const_iterator begin() const noexcept; - impl::const_iterator end() const noexcept; -private: - std::unordered_map m_objects; -}; - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMCollection.h b/Example/Pods/Realm/include/RLMCollection.h deleted file mode 100644 index 030fcc7..0000000 --- a/Example/Pods/Realm/include/RLMCollection.h +++ /dev/null @@ -1,325 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMRealm, RLMResults, RLMObject, RLMSortDescriptor, RLMNotificationToken, RLMCollectionChange; - -/** - A homogenous collection of `RLMObject` instances. Examples of conforming types include `RLMArray`, - `RLMResults`, and `RLMLinkingObjects`. - */ -@protocol RLMCollection - -@required - -#pragma mark - Properties - -/** - The number of objects in the collection. - */ -@property (nonatomic, readonly, assign) NSUInteger count; - -/** - The class name (i.e. type) of the `RLMObject`s contained in the collection. - */ -@property (nonatomic, readonly, copy) NSString *objectClassName; - -/** - The Realm which manages the collection, or `nil` for unmanaged collections. - */ -@property (nonatomic, readonly) RLMRealm *realm; - -#pragma mark - Accessing Objects from a Collection - -/** - Returns the object at the index specified. - - @param index The index to look up. - - @return An `RLMObject` of the type contained in the collection. - */ -- (id)objectAtIndex:(NSUInteger)index; - -/** - Returns the first object in the collection. - - Returns `nil` if called on an empty collection. - - @return An `RLMObject` of the type contained in the collection. - */ -- (nullable id)firstObject; - -/** - Returns the last object in the collection. - - Returns `nil` if called on an empty collection. - - @return An `RLMObject` of the type contained in the collection. - */ -- (nullable id)lastObject; - -#pragma mark - Querying a Collection - -/** - Returns the index of an object in the collection. - - Returns `NSNotFound` if the object is not found in the collection. - - @param object An object (of the same type as returned from the `objectClassName` selector). - */ -- (NSUInteger)indexOfObject:(RLMObject *)object; - -/** - Returns the index of the first object in the collection matching the predicate. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return The index of the object, or `NSNotFound` if the object is not found in the collection. - */ -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns the index of the first object in the collection matching the predicate. - - @param predicate The predicate with which to filter the objects. - - @return The index of the object, or `NSNotFound` if the object is not found in the collection. - */ -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate; - -/** - Returns all objects matching the given predicate in the collection. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return An `RLMResults` containing objects that match the given predicate. - */ -- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns all objects matching the given predicate in the collection. - - @param predicate The predicate with which to filter the objects. - - @return An `RLMResults` containing objects that match the given predicate. - */ -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate; - -/** - Returns a sorted `RLMResults` from the collection. - - @param property The property name to sort by. - @param ascending The direction to sort in. - - @return An `RLMResults` sorted by the specified property. - */ -- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending; - -/** - Returns a sorted `RLMResults` from the collection. - - @param properties An array of `RLMSortDescriptor`s to sort by. - - @return An `RLMResults` sorted by the specified properties. - */ -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; - -/// :nodoc: -- (id)objectAtIndexedSubscript:(NSUInteger)index; - -/** - Returns an `NSArray` containing the results of invoking `valueForKey:` using `key` on each of the collection's objects. - - @param key The name of the property. - - @return An `NSArray` containing results. - */ -- (nullable id)valueForKey:(NSString *)key; - -/** - Invokes `setValue:forKey:` on each of the collection's objects using the specified `value` and `key`. - - @warning This method may only be called during a write transaction. - - @param value The object value. - @param key The name of the property. - */ -- (void)setValue:(nullable id)value forKey:(NSString *)key; - -#pragma mark - Notifications - -/** - Registers a block to be called each time the collection changes. - - The block will be asynchronously called with the initial collection, and then - called again after each write transaction which changes either any of the - objects in the collection, or which objects are in the collection. - - The `change` parameter will be `nil` the first time the block is called. - For each call after that, it will contain information about - which rows in the collection were added, removed or modified. If a write transaction - did not modify any objects in this collection, the block is not called at all. - See the `RLMCollectionChange` documentation for information on how the changes - are reported and an example of updating a `UITableView`. - - If an error occurs the block will be called with `nil` for the collection - parameter and a non-`nil` error. Currently the only errors that can occur are - when opening the Realm on the background worker thread. - - At the time when the block is called, the collection object will be fully - evaluated and up-to-date, and as long as you do not perform a write transaction - on the same thread or explicitly call `-[RLMRealm refresh]`, accessing it will - never perform blocking work. - - Notifications are delivered via the standard run loop, and so can't be - delivered while the run loop is blocked by other activity. When - notifications can't be delivered instantly, multiple notifications may be - coalesced into a single notification. This can include the notification - with the initial collection. For example, the following code performs a write - transaction immediately after adding the notification block, so there is no - opportunity for the initial notification to be delivered first. As a - result, the initial notification will reflect the state of the Realm after - the write transaction. - - id collection = [Dog allObjects]; - NSLog(@"dogs.count: %zu", dogs.count); // => 0 - self.token = [collection addNotificationBlock:^(id dogs, - RLMCollectionChange *changes, - NSError *error) { - // Only fired once for the example - NSLog(@"dogs.count: %zu", dogs.count); // => 1 - }]; - [realm transactionWithBlock:^{ - Dog *dog = [[Dog alloc] init]; - dog.name = @"Rex"; - [realm addObject:dog]; - }]; - // end of run loop execution context - - You must retain the returned token for as long as you want updates to continue - to be sent to the block. To stop receiving updates, call `-stop` on the token. - - @warning This method cannot be called during a write transaction, or when the - containing Realm is read-only. - - @param block The block to be called each time the collection changes. - @return A token which must be held for as long as you want collection notifications to be delivered. - */ -- (RLMNotificationToken *)addNotificationBlock:(void (^)(id __nullable collection, - RLMCollectionChange *__nullable change, - NSError *__nullable error))block __attribute__((warn_unused_result)); - -@end - -/** - An `RLMSortDescriptor` stores a property name and a sort order for use with - `sortedResultsUsingDescriptors:`. It is similar to `NSSortDescriptor`, but supports - only the subset of functionality which can be efficiently run by Realm's query - engine. - - `RLMSortDescriptor` instances are immutable. - */ -@interface RLMSortDescriptor : NSObject - -#pragma mark - Properties - -/** - The name of the property which the sort descriptor orders results by. - */ -@property (nonatomic, readonly) NSString *property; - -/** - Whether the descriptor sorts in ascending or descending order. - */ -@property (nonatomic, readonly) BOOL ascending; - -#pragma mark - Methods - -/** - Returns a new sort descriptor for the given property name and sort direction. - */ -+ (instancetype)sortDescriptorWithProperty:(NSString *)propertyName ascending:(BOOL)ascending; - -/** - Returns a copy of the receiver with the sort direction reversed. - */ -- (instancetype)reversedSortDescriptor; - -@end - -/** - A `RLMCollectionChange` object encapsulates information about changes to collections - that are reported by Realm notifications. - - `RLMCollectionChange` is passed to the notification blocks registered with - `-addNotificationBlock` on `RLMArray` and `RLMResults`, and reports what rows in the - collection changed since the last time the notification block was called. - - The change information is available in two formats: a simple array of row - indices in the collection for each type of change, and an array of index paths - in a requested section suitable for passing directly to `UITableView`'s batch - update methods. A complete example of updating a `UITableView` named `tv`: - - [tv beginUpdates]; - [tv deleteRowsAtIndexPaths:[changes deletionsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic]; - [tv insertRowsAtIndexPaths:[changes insertionsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic]; - [tv reloadRowsAtIndexPaths:[changes modificationsInSection:0] withRowAnimation:UITableViewRowAnimationAutomatic]; - [tv endUpdates]; - - All of the arrays in an `RLMCollectionChange` are always sorted in ascending order. - */ -@interface RLMCollectionChange : NSObject -/// The indices of objects in the previous version of the collection which have -/// been removed from this one. -@property (nonatomic, readonly) NSArray *deletions; - -/// The indices in the new version of the collection which were newly inserted. -@property (nonatomic, readonly) NSArray *insertions; - -/** - The indices in the new version of the collection which were modified. - - For `RLMResults`, this means that one or more of the properties of the object at - that index were modified (or an object linked to by that object was - modified). - - For `RLMArray`, the array itself being modified to contain a - different object at that index will also be reported as a modification. - */ -@property (nonatomic, readonly) NSArray *modifications; - -/// Returns the index paths of the deletion indices in the given section. -- (NSArray *)deletionsInSection:(NSUInteger)section; - -/// Returns the index paths of the insertion indices in the given section. -- (NSArray *)insertionsInSection:(NSUInteger)section; - -/// Returns the index paths of the modification indices in the given section. -- (NSArray *)modificationsInSection:(NSUInteger)section; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMCollection_Private.hpp b/Example/Pods/Realm/include/RLMCollection_Private.hpp deleted file mode 100644 index 9f58c97..0000000 --- a/Example/Pods/Realm/include/RLMCollection_Private.hpp +++ /dev/null @@ -1,77 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import - -namespace realm { - class List; - class Results; - class TableView; - struct CollectionChangeSet; - struct NotificationToken; -} -class RLMClassInfo; - -@protocol RLMFastEnumerable -@property (nonatomic, readonly) RLMRealm *realm; -@property (nonatomic, readonly) RLMClassInfo *objectInfo; -@property (nonatomic, readonly) NSUInteger count; - -- (NSUInteger)indexInSource:(NSUInteger)index; -- (realm::TableView)tableView; -@end - -// An object which encapulates the shared logic for fast-enumerating RLMArray -// and RLMResults, and has a buffer to store strong references to the current -// set of enumerated items -@interface RLMFastEnumerator : NSObject -- (instancetype)initWithCollection:(id)collection - objectSchema:(RLMClassInfo&)objectSchema; - -// Detach this enumerator from the source collection. Must be called before the -// source collection is changed. -- (void)detach; - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - count:(NSUInteger)len; -@end - -@interface RLMNotificationToken () -- (void)suppressNextNotification; -- (RLMRealm *)realm; -@end - -@interface RLMCancellationToken : RLMNotificationToken -- (instancetype)initWithToken:(realm::NotificationToken)token realm:(RLMRealm *)realm; -@end - -@interface RLMCollectionChange () -- (instancetype)initWithChanges:(realm::CollectionChangeSet)indices; -@end - -template -RLMNotificationToken *RLMAddNotificationBlock(id objcCollection, - Collection& collection, - void (^block)(id, RLMCollectionChange *, NSError *), - bool suppressInitialChange=false); - -NSArray *RLMCollectionValueForKey(id collection, NSString *key); -void RLMCollectionSetValueForKey(id collection, NSString *key, id value); -NSString *RLMDescriptionWithMaxDepth(NSString *name, id collection, NSUInteger depth); diff --git a/Example/Pods/Realm/include/RLMConstants.h b/Example/Pods/Realm/include/RLMConstants.h deleted file mode 100644 index bf3b2e7..0000000 --- a/Example/Pods/Realm/include/RLMConstants.h +++ /dev/null @@ -1,204 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -// For compatibility with Xcode 7, before extensible string enums were introduced, -#ifdef NS_EXTENSIBLE_STRING_ENUM -#define RLM_EXTENSIBLE_STRING_ENUM NS_EXTENSIBLE_STRING_ENUM -#define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(_, extensible_string_enum) NS_SWIFT_NAME(extensible_string_enum) -#else -#define RLM_EXTENSIBLE_STRING_ENUM -#define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(fully_qualified, _) NS_SWIFT_NAME(fully_qualified) -#endif - -#if __has_attribute(ns_error_domain) && (!defined(__cplusplus) || !__cplusplus || __cplusplus >= 201103L) -#define RLM_ERROR_ENUM(type, name, domain) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wignored-attributes\"") \ - NS_ENUM(type, __attribute__((ns_error_domain(domain))) name) \ - _Pragma("clang diagnostic pop") -#else -#define RLM_ERROR_ENUM(type, name, domain) NS_ENUM(type, name) -#endif - - -#pragma mark - Enums - -/** - `RLMPropertyType` is an enumeration describing all property types supported in Realm models. - - For more information, see [Realm Models](https://realm.io/docs/objc/latest/#models). - */ -// Make sure numbers match those in -typedef NS_ENUM(int32_t, RLMPropertyType) { - -#pragma mark - Primitive types - - /** Integers: `NSInteger`, `int`, `long`, `Int` (Swift) */ - RLMPropertyTypeInt = 0, - /** Booleans: `BOOL`, `bool`, `Bool` (Swift) */ - RLMPropertyTypeBool = 1, - /** Floating-point numbers: `float`, `Float` (Swift) */ - RLMPropertyTypeFloat = 9, - /** Double-precision floating-point numbers: `double`, `Double` (Swift) */ - RLMPropertyTypeDouble = 10, - -#pragma mark - Object types - - /** Strings: `NSString`, `String` (Swift) */ - RLMPropertyTypeString = 2, - /** Binary data: `NSData` */ - RLMPropertyTypeData = 4, - /** - Any object: `id`. - - This property type is no longer supported for new models. However, old models with any-typed properties are still - supported for migration purposes. - */ - RLMPropertyTypeAny = 6, - /** Dates: `NSDate` */ - RLMPropertyTypeDate = 8, - -#pragma mark - Array/Linked object types - - /** Realm model objects. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */ - RLMPropertyTypeObject = 12, - /** Realm arrays. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */ - RLMPropertyTypeArray = 13, - /** Realm linking objects. See [Realm Models](https://realm.io/docs/objc/latest/#models) for more information. */ - RLMPropertyTypeLinkingObjects = 14, -}; - -/** An error domain identifying Realm-specific errors. */ -extern NSString * const RLMErrorDomain; - -/** An error domain identifying non-specific system errors. */ -extern NSString * const RLMUnknownSystemErrorDomain; - -/** - `RLMError` is an enumeration representing all recoverable errors. It is associated with the - Realm error domain specified in `RLMErrorDomain`. - */ -typedef RLM_ERROR_ENUM(NSInteger, RLMError, RLMErrorDomain) { - /** Denotes a general error that occurred when trying to open a Realm. */ - RLMErrorFail = 1, - - /** Denotes a file I/O error that occurred when trying to open a Realm. */ - RLMErrorFileAccess = 2, - - /** - Denotes a file permission error that ocurred when trying to open a Realm. - - This error can occur if the user does not have permission to open or create - the specified file in the specified access mode when opening a Realm. - */ - RLMErrorFilePermissionDenied = 3, - - /** Denotes an error where a file was to be written to disk, but another file with the same name already exists. */ - RLMErrorFileExists = 4, - - /** - Denotes an error that occurs if a file could not be found. - - This error may occur if a Realm file could not be found on disk when trying to open a - Realm as read-only, or if the directory part of the specified path was not found when - trying to write a copy. - */ - RLMErrorFileNotFound = 5, - - /** - Denotes an error that occurs if a file format upgrade is required to open the file, - but upgrades were explicitly disabled. - */ - RLMErrorFileFormatUpgradeRequired = 6, - - /** - Denotes an error that occurs if the database file is currently open in another - process which cannot share with the current process due to an - architecture mismatch. - - This error may occur if trying to share a Realm file between an i386 (32-bit) iOS - Simulator and the Realm Browser application. In this case, please use the 64-bit - version of the iOS Simulator. - */ - RLMErrorIncompatibleLockFile = 8, - - /** Denotes an error that occurs when there is insufficient available address space. */ - RLMErrorAddressSpaceExhausted = 9, - - /** Denotes an error that occurs if there is a schema version mismatch, so that a migration is required. */ - RLMErrorSchemaMismatch = 10, -}; - -#pragma mark - Constants - -#pragma mark - Notification Constants - -/** - A notification indicating that changes were made to a Realm. -*/ -typedef NSString * RLMNotification RLM_EXTENSIBLE_STRING_ENUM; - -/** - This notification is posted by a Realm when the data in that Realm has changed. - - More specifically, this notification is posted after a Realm has been refreshed to - reflect a write transaction. This can happen when an autorefresh occurs, when - `-[RLMRealm refresh]` is called, after an implicit refresh from `-[RLMRealm beginWriteTransaction]`, - or after a local write transaction is completed. - */ -extern RLMNotification const RLMRealmRefreshRequiredNotification -RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(RLMRealmRefreshRequiredNotification, RefreshRequired); - -/** - This notification is posted by a Realm when a write transaction has been - committed to a Realm on a different thread for the same file. - - It is not posted if `-[RLMRealm autorefresh]` is enabled, or if the Realm is - refreshed before the notification has a chance to run. - - Realms with autorefresh disabled should normally install a handler for this - notification which calls `-[RLMRealm refresh]` after doing some work. Refreshing - the Realm is optional, but not refreshing the Realm may lead to large Realm - files. This is because Realm must keep an extra copy of the data for the stale - Realm. - */ -extern RLMNotification const RLMRealmDidChangeNotification -RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(RLMRealmDidChangeNotification, DidChange); - -#pragma mark - Other Constants - -/** The schema version used for uninitialized Realms */ -extern const uint64_t RLMNotVersioned; - -/** The corresponding value is the name of an exception thrown by Realm. */ -extern NSString * const RLMExceptionName; - -/** The corresponding value is a Realm file version. */ -extern NSString * const RLMRealmVersionKey; - -/** The corresponding key is the version of the underlying database engine. */ -extern NSString * const RLMRealmCoreVersionKey; - -/** The corresponding key is the Realm invalidated property name. */ -extern NSString * const RLMInvalidatedKey; - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMListBase.h b/Example/Pods/Realm/include/RLMListBase.h deleted file mode 100644 index 0151cfb..0000000 --- a/Example/Pods/Realm/include/RLMListBase.h +++ /dev/null @@ -1,33 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -@class RLMArray; - -NS_ASSUME_NONNULL_BEGIN - -// A base class for Swift generic Lists to make it possible to interact with -// them from obj-c -@interface RLMListBase : NSObject -@property (nonatomic, strong) RLMArray *_rlmArray; - -- (instancetype)initWithArray:(RLMArray *)array; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMMigration.h b/Example/Pods/Realm/include/RLMMigration.h deleted file mode 100644 index d3da9ff..0000000 --- a/Example/Pods/Realm/include/RLMMigration.h +++ /dev/null @@ -1,127 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMSchema; -@class RLMArray; -@class RLMObject; - -/** - A block type which provides both the old and new versions of an object in the Realm. Object - properties can only be accessed using keyed subscripting. - - @see `-[RLMMigration enumerateObjects:block:]` - - @param oldObject The object from the original Realm (read-only). - @param newObject The object from the migrated Realm (read-write). -*/ -typedef void (^RLMObjectMigrationBlock)(RLMObject * __nullable oldObject, RLMObject * __nullable newObject); - -/** - `RLMMigration` instances encapsulate information intended to facilitate a schema migration. - - A `RLMMigration` instance is passed into a user-defined `RLMMigrationBlock` block when updating - the version of a Realm. This instance provides access to the old and new database schemas, the - objects in the Realm, and provides functionality for modifying the Realm during the migration. - */ -@interface RLMMigration : NSObject - -#pragma mark - Properties - -/** - Returns the old `RLMSchema`. This is the schema which describes the Realm before the - migration is applied. - */ -@property (nonatomic, readonly) RLMSchema *oldSchema; - -/** - Returns the new `RLMSchema`. This is the schema which describes the Realm after the - migration is applied. - */ -@property (nonatomic, readonly) RLMSchema *newSchema; - - -#pragma mark - Altering Objects during a Migration - -/** - Enumerates all the objects of a given type in the Realm, providing both the old and new versions - of each object. Within the block, object properties can only be accessed using keyed subscripting. - - @param className The name of the `RLMObject` class to enumerate. - - @warning All objects returned are of a type specific to the current migration and should not be cast - to `className`. Instead, treat them as `RLMObject`s and use keyed subscripting to access - properties. - */ -- (void)enumerateObjects:(NSString *)className block:(__attribute__((noescape)) RLMObjectMigrationBlock)block; - -/** - Creates and returns an `RLMObject` instance of type `className` in the Realm being migrated. - - The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or - dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed - property. An exception will be thrown if any required properties are not present and those properties were not defined - with default values. - - When passing in an `NSArray` as the `value` argument, all properties must be present, valid and in the same order as - the properties defined in the model. - - @param className The name of the `RLMObject` class to create. - @param value The value used to populate the object. - */ -- (RLMObject *)createObject:(NSString *)className withValue:(id)value; - -/** - Deletes an object from a Realm during a migration. - - It is permitted to call this method from within the block passed to `-[enumerateObjects:block:]`. - - @param object Object to be deleted from the Realm being migrated. - */ -- (void)deleteObject:(RLMObject *)object; - -/** - Deletes the data for the class with the given name. - - All objects of the given class will be deleted. If the `RLMObject` subclass no longer exists in your program, - any remaining metadata for the class will be removed from the Realm file. - - @param name The name of the `RLMObject` class to delete. - - @return A Boolean value indicating whether there was any data to delete. - */ -- (BOOL)deleteDataForClassName:(NSString *)name; - -/** - Renames a property of the given class from `oldName` to `newName`. - - @param className The name of the class whose property should be renamed. This class must be present - in both the old and new Realm schemas. - @param oldName The old name for the property to be renamed. There must not be a property with this name in the - class as defined by the new Realm schema. - @param newName The new name for the property to be renamed. There must not be a property with this name in the - class as defined by the old Realm schema. - */ -- (void)renamePropertyForClass:(NSString *)className oldName:(NSString *)oldName newName:(NSString *)newName; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMMigration_Private.h b/Example/Pods/Realm/include/RLMMigration_Private.h deleted file mode 100644 index 99699e5..0000000 --- a/Example/Pods/Realm/include/RLMMigration_Private.h +++ /dev/null @@ -1,40 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import -#import - -namespace realm { - class Schema; -} - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMMigration () - -@property (nonatomic, strong) RLMRealm *oldRealm; -@property (nonatomic, strong) RLMRealm *realm; - -- (instancetype)initWithRealm:(RLMRealm *)realm oldRealm:(RLMRealm *)oldRealm schema:(realm::Schema &)schema; - -- (void)execute:(RLMMigrationBlock)block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMNetworkClient.h b/Example/Pods/Realm/include/RLMNetworkClient.h deleted file mode 100644 index bde6ecf..0000000 --- a/Example/Pods/Realm/include/RLMNetworkClient.h +++ /dev/null @@ -1,57 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil_Private.h" - -/** - An enum describing all possible endpoints on the Realm Object Server. - */ -typedef NS_ENUM(NSUInteger, RLMServerEndpoint) { - RLMServerEndpointAuth, - RLMServerEndpointLogout, - RLMServerEndpointAddCredentials, - RLMServerEndpointRemoveCredentials, -}; - -/** - A simple Realm Object Server network client that wraps `NSURLSession`. - */ -@interface RLMNetworkClient : NSObject - -NS_ASSUME_NONNULL_BEGIN - -+ (void)postRequestToEndpoint:(RLMServerEndpoint)endpoint - server:(NSURL *)serverURL - JSON:(NSDictionary *)jsonDictionary - completion:(RLMSyncCompletionBlock)completionBlock; - -/** - Post some JSON data to the authentication server, and asynchronously call a completion block with a JSON response - and/or error. - */ -+ (void)postRequestToEndpoint:(RLMServerEndpoint)endpoint - server:(NSURL *)serverURL - JSON:(NSDictionary *)jsonDictionary - timeout:(NSTimeInterval)timeout - completion:(RLMSyncCompletionBlock)completionBlock; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMObject.h b/Example/Pods/Realm/include/RLMObject.h deleted file mode 100644 index 407a258..0000000 --- a/Example/Pods/Realm/include/RLMObject.h +++ /dev/null @@ -1,445 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class RLMPropertyDescriptor; -@class RLMRealm; -@class RLMResults; -@class RLMObjectSchema; - -/** - `RLMObject` is a base class for model objects representing data stored in Realms. - - Define your model classes by subclassing `RLMObject` and adding properties to be managed. - Then instantiate and use your custom subclasses instead of using the `RLMObject` class directly. - - // Dog.h - @interface Dog : RLMObject - @property NSString *name; - @property BOOL adopted; - @end - - // Dog.m - @implementation Dog - @end //none needed - - ### Supported property types - - - `NSString` - - `NSInteger`, `int`, `long`, `float`, and `double` - - `BOOL` or `bool` - - `NSDate` - - `NSData` - - `NSNumber`, where `X` is one of `RLMInt`, `RLMFloat`, `RLMDouble` or `RLMBool`, for optional number properties - - `RLMObject` subclasses, to model many-to-one relationships. - - `RLMArray`, where `X` is an `RLMObject` subclass, to model many-to-many relationships. - - ### Querying - - You can initiate queries directly via the class methods: `allObjects`, `objectsWhere:`, and `objectsWithPredicate:`. - These methods allow you to easily query a custom subclass for instances of that class in the default Realm. - - To search in a Realm other than the default Realm, use the `allObjectsInRealm:`, `objectsInRealm:where:`, - and `objectsInRealm:withPredicate:` class methods. - - @see `RLMRealm` - - ### Relationships - - See our [Cocoa guide](https://realm.io/docs/objc/latest#relationships) for more details. - - ### Key-Value Observing - - All `RLMObject` properties (including properties you create in subclasses) are - [Key-Value Observing compliant](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html), - except for `realm` and `objectSchema`. - - Keep the following tips in mind when observing Realm objects: - - 1. Unlike `NSMutableArray` properties, `RLMArray` properties do not require - using the proxy object returned from `-mutableArrayValueForKey:`, or defining - KVC mutation methods on the containing class. You can simply call methods on - the `RLMArray` directly; any changes will be automatically observed by the containing - object. - 2. Unmanaged `RLMObject` instances cannot be added to a Realm while they have any - observed properties. - 3. Modifying managed `RLMObject`s within `-observeValueForKeyPath:ofObject:change:context:` - is not recommended. Properties may change even when the Realm is not in a write - transaction (for example, when `-[RLMRealm refresh]` is called after changes - are made on a different thread), and notifications sent prior to the change - being applied (when `NSKeyValueObservingOptionPrior` is used) may be sent at - times when you *cannot* begin a write transaction. - */ - -@interface RLMObject : RLMObjectBase - -#pragma mark - Creating & Initializing Objects - -/** - Creates an unmanaged instance of a Realm object. - - Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm. - - @see `[RLMRealm addObject:]` - */ -- (instancetype)init NS_DESIGNATED_INITIALIZER; - - -/** - Creates an unmanaged instance of a Realm object. - - Pass in an `NSArray` or `NSDictionary` instance to set the values of the object's properties. - - Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm. - - @see `[RLMRealm addObject:]` - */ -- (instancetype)initWithValue:(id)value NS_DESIGNATED_INITIALIZER; - - -/** - Returns the class name for a Realm object subclass. - - @warning Do not override. Realm relies on this method returning the exact class - name. - - @return The class name for the model class. - */ -+ (NSString *)className; - -/** - Creates an instance of a Realm object with a given value, and adds it to the default Realm. - - If nested objects are included in the argument, `createInDefaultRealmWithValue:` will be recursively called - on them. - - The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in - `NSJSONSerialization`, or an array containing one element for each managed property. An exception will be thrown if - any required properties are not present and those properties were not defined with default values. - - When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the - properties defined in the model. - - @param value The value used to populate the object. - - @see `defaultPropertyValues` - */ -+ (instancetype)createInDefaultRealmWithValue:(id)value; - -/** - Creates an instance of a Realm object with a given value, and adds it to the specified Realm. - - If nested objects are included in the argument, `createInRealm:withValue:` will be recursively called - on them. - - The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in - `NSJSONSerialization`, or an array containing one element for each managed property. An exception will be thrown if any - required properties are not present and those properties were not defined with default values. - - When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the - properties defined in the model. - - @param realm The Realm which should manage the newly-created object. - @param value The value used to populate the object. - - @see `defaultPropertyValues` - */ -+ (instancetype)createInRealm:(RLMRealm *)realm withValue:(id)value; - -/** - Creates or updates a Realm object within the default Realm. - - This method may only be called on Realm object types with a primary key defined. If there is already - an object with the same primary key value in the default Realm, its values are updated and the object - is returned. Otherwise, this method creates and populates a new instance of the object in the default Realm. - - If nested objects are included in the argument, `createOrUpdateInDefaultRealmWithValue:` will be - recursively called on them if they have primary keys, `createInDefaultRealmWithValue:` if they do not. - - If the argument is a Realm object already managed by the default Realm, the argument's type is the same - as the receiver, and the objects have identical values for their managed properties, this method does nothing. - - The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or - dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed - property. An exception will be thrown if any required properties are not present and those properties were not defined - with default values. - - When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the - properties defined in the model. - - @param value The value used to populate the object. - - @see `defaultPropertyValues`, `primaryKey` - */ -+ (instancetype)createOrUpdateInDefaultRealmWithValue:(id)value; - -/** - Creates or updates an Realm object within a specified Realm. - - This method may only be called on Realm object types with a primary key defined. If there is already - an object with the same primary key value in the given Realm, its values are updated and the object - is returned. Otherwise this method creates and populates a new instance of this object in the given Realm. - - If nested objects are included in the argument, `createOrUpdateInRealm:withValue:` will be - recursively called on them if they have primary keys, `createInRealm:withValue:` if they do not. - - If the argument is a Realm object already managed by the given Realm, the argument's type is the same - as the receiver, and the objects have identical values for their managed properties, this method does nothing. - - The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or - dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed - property. An exception will be thrown if any required properties are not present and those properties were not defined - with default values. - - When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the - properties defined in the model. - - @param realm The Realm which should own the object. - @param value The value used to populate the object. - - @see `defaultPropertyValues`, `primaryKey` - */ -+ (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value; - -#pragma mark - Properties - -/** - The Realm which manages the object, or `nil` if the object is unmanaged. - */ -@property (nonatomic, readonly, nullable) RLMRealm *realm; - -/** - The object schema which lists the managed properties for the object. - */ -@property (nonatomic, readonly) RLMObjectSchema *objectSchema; - -/** - Indicates if the object can no longer be accessed because it is now invalid. - - An object can no longer be accessed if the object has been deleted from the Realm that manages it, or - if `invalidate` is called on that Realm. - */ -@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated; - - -#pragma mark - Customizing your Objects - -/** - Returns an array of property names for properties which should be indexed. - - Only string, integer, boolean, and `NSDate` properties are supported. - - @return An array of property names. - */ -+ (NSArray *)indexedProperties; - -/** - Override this method to specify the default values to be used for each property. - - @return A dictionary mapping property names to their default values. - */ -+ (nullable NSDictionary *)defaultPropertyValues; - -/** - Override this method to specify the name of a property to be used as the primary key. - - Only properties of types `RLMPropertyTypeString` and `RLMPropertyTypeInt` can be designated as the primary key. - Primary key properties enforce uniqueness for each value whenever the property is set, which incurs minor overhead. - Indexes are created automatically for primary key properties. - - @return The name of the property designated as the primary key. - */ -+ (nullable NSString *)primaryKey; - -/** - Override this method to specify the names of properties to ignore. These properties will not be managed by the Realm - that manages the object. - - @return An array of property names to ignore. - */ -+ (nullable NSArray *)ignoredProperties; - -/** - Override this method to specify the names of properties that are non-optional (i.e. cannot be assigned a `nil` value). - - By default, all properties of a type whose values can be set to `nil` are considered optional properties. - To require that an object in a Realm always store a non-`nil` value for a property, - add the name of the property to the array returned from this method. - - Properties of `RLMObject` type cannot be non-optional. Array and `NSNumber` properties - can be non-optional, but there is no reason to do so: arrays do not support storing nil, and - if you want a non-optional number you should instead use the primitive type. - - @return An array of property names that are required. - */ -+ (NSArray *)requiredProperties; - -/** - Override this method to provide information related to properties containing linking objects. - - Each property of type `RLMLinkingObjects` must have a key in the dictionary returned by this method consisting - of the property name. The corresponding value must be an instance of `RLMPropertyDescriptor` that describes the class - and property that the property is linked to. - - return @{ @"owners": [RLMPropertyDescriptor descriptorWithClass:Owner.class propertyName:@"dogs"] }; - - @return A dictionary mapping property names to `RLMPropertyDescriptor` instances. - */ -+ (NSDictionary *)linkingObjectsProperties; - - -#pragma mark - Getting & Querying Objects from the Default Realm - -/** - Returns all objects of this object type from the default Realm. - - @return An `RLMResults` containing all objects of this type in the default Realm. - */ -+ (RLMResults *)allObjects; - -/** - Returns all objects of this object type matching the given predicate from the default Realm. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate. - */ -+ (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - - -/** - Returns all objects of this object type matching the given predicate from the default Realm. - - @param predicate The predicate with which to filter the objects. - - @return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate. - */ -+ (RLMResults *)objectsWithPredicate:(nullable NSPredicate *)predicate; - -/** - Retrieves the single instance of this object type with the given primary key from the default Realm. - - Returns the object from the default Realm which has the given primary key, or - `nil` if the object does not exist. This is slightly faster than the otherwise - equivalent `[[SubclassName objectsWhere:@"primaryKeyPropertyName = %@", key] firstObject]`. - - This method requires that `primaryKey` be overridden on the receiving subclass. - - @return An object of this object type, or `nil` if an object with the given primary key does not exist. - @see `-primaryKey` - */ -+ (nullable instancetype)objectForPrimaryKey:(nullable id)primaryKey; - - -#pragma mark - Querying Specific Realms - -/** - Returns all objects of this object type from the specified Realm. - - @param realm The Realm to query. - - @return An `RLMResults` containing all objects of this type in the specified Realm. - */ -+ (RLMResults *)allObjectsInRealm:(RLMRealm *)realm; - -/** - Returns all objects of this object type matching the given predicate from the specified Realm. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - @param realm The Realm to query. - - @return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate. - */ -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ...; - -/// :nodoc: -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns all objects of this object type matching the given predicate from the specified Realm. - - @param predicate A predicate to use to filter the elements. - @param realm The Realm to query. - - @return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate. - */ -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(nullable NSPredicate *)predicate; - -/** - Retrieves the single instance of this object type with the given primary key from the specified Realm. - - Returns the object from the specified Realm which has the given primary key, or - `nil` if the object does not exist. This is slightly faster than the otherwise - equivalent `[[SubclassName objectsInRealm:realm where:@"primaryKeyPropertyName = %@", key] firstObject]`. - - This method requires that `primaryKey` be overridden on the receiving subclass. - - @return An object of this object type, or `nil` if an object with the given primary key does not exist. - @see `-primaryKey` - */ -+ (nullable instancetype)objectInRealm:(RLMRealm *)realm forPrimaryKey:(nullable id)primaryKey; - -#pragma mark - Other Instance Methods - -/** - Returns YES if another Realm object instance points to the same object as the receiver in the Realm managing - the receiver. - - For object types with a primary, key, `isEqual:` is overridden to use this method (along with a corresponding - implementation for `hash`). - - @param object The object to compare the receiver to. - - @return Whether the object represents the same object as the receiver. - */ -- (BOOL)isEqualToObject:(RLMObject *)object; - -#pragma mark - Dynamic Accessors - -/// :nodoc: -- (nullable id)objectForKeyedSubscript:(NSString *)key; - -/// :nodoc: -- (void)setObject:(nullable id)obj forKeyedSubscript:(NSString *)key; - -@end - -#pragma mark - RLMArray Property Declaration - -/** - Properties on `RLMObject`s of type `RLMArray` must have an associated type. A type is associated - with an `RLMArray` property by defining a protocol for the object type that the array should contain. - To define the protocol for an object, you can use the macro RLM_ARRAY_TYPE: - - RLM_ARRAY_TYPE(ObjectType) - ... - @property RLMArray *arrayOfObjectTypes; - */ -#define RLM_ARRAY_TYPE(RLM_OBJECT_SUBCLASS)\ -@protocol RLM_OBJECT_SUBCLASS \ -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObjectBase.h b/Example/Pods/Realm/include/RLMObjectBase.h deleted file mode 100644 index 6b3271f..0000000 --- a/Example/Pods/Realm/include/RLMObjectBase.h +++ /dev/null @@ -1,43 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMRealm; -@class RLMSchema; -@class RLMObjectSchema; - -/// :nodoc: -@interface RLMObjectBase : NSObject - -@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated; - -- (instancetype)init NS_DESIGNATED_INITIALIZER; - -+ (NSString *)className; - -// Returns whether the class is included in the default set of classes managed by a Realm. -+ (BOOL)shouldIncludeInDefaultSchema; - -+ (nullable NSString *)_realmObjectName; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObjectBase_Dynamic.h b/Example/Pods/Realm/include/RLMObjectBase_Dynamic.h deleted file mode 100644 index 08f25d5..0000000 --- a/Example/Pods/Realm/include/RLMObjectBase_Dynamic.h +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -@class RLMObjectSchema, RLMRealm; - -NS_ASSUME_NONNULL_BEGIN - -/** - Returns the Realm that manages the object, if one exists. - - @warning This function is useful only in specialized circumstances, for example, when building components - that integrate with Realm. If you are simply building an app on Realm, it is - recommended to retrieve the Realm that manages the object via `RLMObject`. - - @param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`. - - @return The Realm which manages this object. Returns `nil `for unmanaged objects. - */ -FOUNDATION_EXTERN RLMRealm * _Nullable RLMObjectBaseRealm(RLMObjectBase * _Nullable object); - -/** - Returns an `RLMObjectSchema` which describes the managed properties of the object. - - @warning This function is useful only in specialized circumstances, for example, when building components - that integrate with Realm. If you are simply building an app on Realm, it is - recommended to retrieve `objectSchema` via `RLMObject`. - - @param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`. - - @return The object schema which lists the managed properties for the object. - */ -FOUNDATION_EXTERN RLMObjectSchema * _Nullable RLMObjectBaseObjectSchema(RLMObjectBase * _Nullable object); - -/** - Returns the object corresponding to a key value. - - @warning This function is useful only in specialized circumstances, for example, when building components - that integrate with Realm. If you are simply building an app on Realm, it is - recommended to retrieve key values via `RLMObject`. - - @warning Will throw an `NSUndefinedKeyException` if `key` is not present on the object. - - @param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`. - @param key The name of the property. - - @return The object for the property requested. - */ -FOUNDATION_EXTERN id _Nullable RLMObjectBaseObjectForKeyedSubscript(RLMObjectBase * _Nullable object, NSString *key); - -/** - Sets a value for a key on the object. - - @warning This function is useful only in specialized circumstances, for example, when building components - that integrate with Realm. If you are simply building an app on Realm, it is - recommended to set key values via `RLMObject`. - - @warning Will throw an `NSUndefinedKeyException` if `key` is not present on the object. - - @param object An `RLMObjectBase` obtained via a Swift `Object` or `RLMObject`. - @param key The name of the property. - @param obj The object to set as the value of the key. - */ -FOUNDATION_EXTERN void RLMObjectBaseSetObjectForKeyedSubscript(RLMObjectBase * _Nullable object, NSString *key, id _Nullable obj); - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObjectSchema.h b/Example/Pods/Realm/include/RLMObjectSchema.h deleted file mode 100644 index 808cdfa..0000000 --- a/Example/Pods/Realm/include/RLMObjectSchema.h +++ /dev/null @@ -1,72 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMProperty; - -/** - This class represents Realm model object schemas. - - When using Realm, `RLMObjectSchema` instances allow performing migrations and - introspecting the database's schema. - - Object schemas map to tables in the core database. - */ -@interface RLMObjectSchema : NSObject - -#pragma mark - Properties - -/** - An array of `RLMProperty` instances representing the managed properties of a class described by the schema. - - @see `RLMProperty` - */ -@property (nonatomic, readonly, copy) NSArray *properties; - -/** - The name of the class the schema describes. - */ -@property (nonatomic, readonly) NSString *className; - -/** - The property which serves as the primary key for the class the schema describes, if any. - */ -@property (nonatomic, readonly, nullable) RLMProperty *primaryKeyProperty; - -#pragma mark - Methods - -/** - Retrieves an `RLMProperty` object by the property name. - - @param propertyName The property's name. - - @return An `RLMProperty` object, or `nil` if there is no property with the given name. - */ -- (nullable RLMProperty *)objectForKeyedSubscript:(NSString *)propertyName; - -/** - Returns whether two `RLMObjectSchema` instances are equal. - */ -- (BOOL)isEqualToObjectSchema:(RLMObjectSchema *)objectSchema; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObjectSchema_Private.h b/Example/Pods/Realm/include/RLMObjectSchema_Private.h deleted file mode 100644 index c2968cc..0000000 --- a/Example/Pods/Realm/include/RLMObjectSchema_Private.h +++ /dev/null @@ -1,71 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import - -NS_ASSUME_NONNULL_BEGIN - -// RLMObjectSchema private -@interface RLMObjectSchema () { -@public - bool _isSwiftClass; -} - -/// The object type name reported to the object store and core. -@property (nonatomic, readonly) NSString *objectName; - -// writable redeclaration -@property (nonatomic, readwrite, copy) NSArray *properties; -@property (nonatomic, readwrite, assign) bool isSwiftClass; - -// class used for this object schema -@property (nonatomic, readwrite, assign) Class objectClass; -@property (nonatomic, readwrite, assign) Class accessorClass; -@property (nonatomic, readwrite, assign) Class unmanagedClass; - -@property (nonatomic, readwrite, nullable) RLMProperty *primaryKeyProperty; - -@property (nonatomic, copy) NSArray *computedProperties; -@property (nonatomic, readonly) NSArray *swiftGenericProperties; - -// returns a cached or new schema for a given object class -+ (instancetype)schemaForObjectClass:(Class)objectClass; -@end - -@interface RLMObjectSchema (Dynamic) -/** - This method is useful only in specialized circumstances, for example, when accessing objects - in a Realm produced externally. If you are simply building an app on Realm, it is not recommended - to use this method as an [RLMObjectSchema](RLMObjectSchema) is generated automatically for every [RLMObject](RLMObject) subclass. - - Initialize an RLMObjectSchema with classname, objectClass, and an array of properties - - @warning This method is useful only in specialized circumstances. - - @param objectClassName The name of the class used to refer to objects of this type. - @param objectClass The Objective-C class used when creating instances of this type. - @param properties An array of RLMProperty instances describing the managed properties for this type. - - @return An initialized instance of RLMObjectSchema. - */ -- (instancetype)initWithClassName:(NSString *)objectClassName objectClass:(Class)objectClass properties:(NSArray *)properties; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObjectSchema_Private.hpp b/Example/Pods/Realm/include/RLMObjectSchema_Private.hpp deleted file mode 100644 index 3d93be2..0000000 --- a/Example/Pods/Realm/include/RLMObjectSchema_Private.hpp +++ /dev/null @@ -1,29 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObjectSchema_Private.h" - -#import "object_schema.hpp" - -@interface RLMObjectSchema () -// create realm::ObjectSchema copy -- (realm::ObjectSchema)objectStoreCopy; - -// initialize with realm::ObjectSchema -+ (instancetype)objectSchemaForObjectStoreSchema:(realm::ObjectSchema const&)objectSchema; -@end diff --git a/Example/Pods/Realm/include/RLMObjectStore.h b/Example/Pods/Realm/include/RLMObjectStore.h deleted file mode 100644 index 3d7f194..0000000 --- a/Example/Pods/Realm/include/RLMObjectStore.h +++ /dev/null @@ -1,104 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#ifdef __cplusplus -extern "C" { -#endif - -@class RLMRealm, RLMSchema, RLMObjectBase, RLMResults, RLMProperty; - -NS_ASSUME_NONNULL_BEGIN - -// -// Accessor Creation -// - -// create or get cached accessors for the given schema -void RLMRealmCreateAccessors(RLMSchema *schema); - - -// -// Options for object creation -// -typedef NS_OPTIONS(NSUInteger, RLMCreationOptions) { - // Normal object creation - RLMCreationOptionsNone = 0, - // If the property is a link or array property, upsert the linked objects - // if they have a primary key, and insert them otherwise. - RLMCreationOptionsCreateOrUpdate = 1 << 0, - // Allow unmanaged objects to be promoted to managed objects - // if false objects are copied during object creation - RLMCreationOptionsPromoteUnmanaged = 1 << 1, - // Use the SetDefault instruction. - RLMCreationOptionsSetDefault = 1 << 2, -}; - - -// -// Adding, Removing, Getting Objects -// - -// add an object to the given realm -void RLMAddObjectToRealm(RLMObjectBase *object, RLMRealm *realm, bool createOrUpdate); - -// delete an object from its realm -void RLMDeleteObjectFromRealm(RLMObjectBase *object, RLMRealm *realm); - -// deletes all objects from a realm -void RLMDeleteAllObjectsFromRealm(RLMRealm *realm); - -// get objects of a given class -RLMResults *RLMGetObjects(RLMRealm *realm, NSString *objectClassName, NSPredicate * _Nullable predicate) -NS_RETURNS_RETAINED; - -// get an object with the given primary key -id _Nullable RLMGetObject(RLMRealm *realm, NSString *objectClassName, id _Nullable key) NS_RETURNS_RETAINED; - -// create object from array or dictionary -RLMObjectBase *RLMCreateObjectInRealmWithValue(RLMRealm *realm, NSString *className, id _Nullable value, bool createOrUpdate) -NS_RETURNS_RETAINED; - - -// -// Accessor Creation -// - - -// switch List<> properties from being backed by unmanaged RLMArrays to RLMArrayLinkView -void RLMInitializeSwiftAccessorGenerics(RLMObjectBase *object); - -#ifdef __cplusplus -} - -namespace realm { - class Table; - template class BasicRowExpr; - using RowExpr = BasicRowExpr; -} -class RLMClassInfo; - -// Create accessors -RLMObjectBase *RLMCreateObjectAccessor(RLMRealm *realm, RLMClassInfo& info, - NSUInteger index) NS_RETURNS_RETAINED; -RLMObjectBase *RLMCreateObjectAccessor(RLMRealm *realm, RLMClassInfo& info, - realm::RowExpr row) NS_RETURNS_RETAINED; -#endif - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObject_Private.h b/Example/Pods/Realm/include/RLMObject_Private.h deleted file mode 100644 index 400f587..0000000 --- a/Example/Pods/Realm/include/RLMObject_Private.h +++ /dev/null @@ -1,98 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -// RLMObject accessor and read/write realm -@interface RLMObjectBase () { -@public - RLMRealm *_realm; - __unsafe_unretained RLMObjectSchema *_objectSchema; -} - -// unmanaged initializer -- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema NS_DESIGNATED_INITIALIZER; - -// live accessor initializer -- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm - schema:(RLMObjectSchema *)schema NS_DESIGNATED_INITIALIZER; - -// shared schema for this class -+ (nullable RLMObjectSchema *)sharedSchema; - -// provide injection point for alternative Swift object util class -+ (Class)objectUtilClass:(BOOL)isSwift; - -@end - -@interface RLMObject () - -// unmanaged initializer -- (instancetype)initWithValue:(id)value schema:(RLMSchema *)schema NS_DESIGNATED_INITIALIZER; - -// live accessor initializer -- (instancetype)initWithRealm:(__unsafe_unretained RLMRealm *const)realm - schema:(RLMObjectSchema *)schema NS_DESIGNATED_INITIALIZER; - -@end - -@interface RLMDynamicObject : RLMObject - -@end - -// A reference to an object's row that doesn't keep the object accessor alive. -// Used by some Swift property types, such as LinkingObjects, to avoid retain cycles -// with their containing object. -@interface RLMWeakObjectHandle : NSObject - -- (instancetype)initWithObject:(RLMObjectBase *)object; - -// Consumes the row, so can only usefully be called once. -@property (nonatomic, readonly) RLMObjectBase *object; - -@end - -// Calls valueForKey: and re-raises NSUndefinedKeyExceptions -FOUNDATION_EXTERN id _Nullable RLMValidatedValueForProperty(id object, NSString *key, NSString *className); - -// Compare two RLObjectBases -FOUNDATION_EXTERN BOOL RLMObjectBaseAreEqual(RLMObjectBase * _Nullable o1, RLMObjectBase * _Nullable o2); - -// Get ObjectUil class for objc or swift -FOUNDATION_EXTERN Class RLMObjectUtilClass(BOOL isSwift); - -FOUNDATION_EXTERN const NSUInteger RLMDescriptionMaxDepth; - -@class RLMProperty, RLMArray; -@interface RLMObjectUtil : NSObject - -+ (nullable NSArray *)ignoredPropertiesForClass:(Class)cls; -+ (nullable NSArray *)indexedPropertiesForClass:(Class)cls; -+ (nullable NSDictionary *> *)linkingObjectsPropertiesForClass:(Class)cls; - -+ (nullable NSArray *)getGenericListPropertyNames:(id)obj; -+ (nullable NSDictionary *)getLinkingObjectsProperties:(id)object; - -+ (nullable NSDictionary *)getOptionalProperties:(id)obj; -+ (nullable NSArray *)requiredPropertiesForClass:(Class)cls; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMObject_Private.hpp b/Example/Pods/Realm/include/RLMObject_Private.hpp deleted file mode 100644 index 7f79dd6..0000000 --- a/Example/Pods/Realm/include/RLMObject_Private.hpp +++ /dev/null @@ -1,58 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMObject_Private.h" - -#import "RLMRealm_Private.hpp" -#import "RLMUtil.hpp" - -#import // required by row.hpp -#import - -class RLMObservationInfo; - -// RLMObject accessor and read/write realm -@interface RLMObjectBase () { - @public - realm::Row _row; - RLMObservationInfo *_observationInfo; - RLMClassInfo *_info; -} -@end - -// FIXME-2.0: This should be folded into initWithRealm:schema:, but changing the -// signature of that is a breaking change for Swift -id RLMCreateManagedAccessor(Class cls, RLMRealm *realm, RLMClassInfo *info) NS_RETURNS_RETAINED; - -// throw an exception if the object is invalidated or on the wrong thread -static inline void RLMVerifyAttached(__unsafe_unretained RLMObjectBase *const obj) { - if (!obj->_row.is_attached()) { - @throw RLMException(@"Object has been deleted or invalidated."); - } - [obj->_realm verifyThread]; -} - -// throw an exception if the object can't be modified for any reason -static inline void RLMVerifyInWriteTransaction(__unsafe_unretained RLMObjectBase *const obj) { - // first verify is attached - RLMVerifyAttached(obj); - - if (!obj->_realm.inWriteTransaction) { - @throw RLMException(@"Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first."); - } -} diff --git a/Example/Pods/Realm/include/RLMObservation.hpp b/Example/Pods/Realm/include/RLMObservation.hpp deleted file mode 100644 index 0f5b215..0000000 --- a/Example/Pods/Realm/include/RLMObservation.hpp +++ /dev/null @@ -1,153 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 - -#import "binding_context.hpp" - -#import -#import - -#import - -@class RLMObjectBase, RLMRealm, RLMSchema, RLMProperty, RLMObjectSchema; -class RLMClassInfo; -class RLMSchemaInfo; - -namespace realm { - class History; - class SharedGroup; -} - -// RLMObservationInfo stores all of the KVO-related data for RLMObjectBase and -// RLMArray. There is a one-to-one relationship between observed objects and -// RLMObservationInfo instances, so it could be folded into RLMObjectBase, and -// is a separate class mostly to avoid making all accessor objects far larger. -// -// RLMClassInfo stores a vector of pointers to the first observation info -// created for each row. If there are multiple observation infos for a single -// row (such as if there are multiple observed objects backed by a single row, -// or if both an object and an array property of that object are observed), -// they're stored in an intrusive doubly-linked-list in the `next` and `prev` -// members. This is done primarily to make it simpler and faster to loop over -// all of the observed objects for a single row, as that needs to be done for -// every change. -class RLMObservationInfo { -public: - RLMObservationInfo(id object); - RLMObservationInfo(RLMClassInfo &objectSchema, std::size_t row, id object); - ~RLMObservationInfo(); - - realm::Row const& getRow() const { - return row; - } - - NSString *columnName(size_t col) const noexcept; - - // Send willChange/didChange notifications to all observers for this object/row - // Sends the array versions if indexes is non-nil, normal versions otherwise - void willChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const; - void didChange(NSString *key, NSKeyValueChange kind=NSKeyValueChangeSetting, NSIndexSet *indexes=nil) const; - - bool isForRow(size_t ndx) const { - return row && row.get_index() == ndx; - } - - void recordObserver(realm::Row& row, RLMClassInfo *objectInfo, RLMObjectSchema *objectSchema, NSString *keyPath); - void removeObserver(); - bool hasObservers() const { return observerCount > 0; } - - // valueForKey: on observed object and array properties needs to return the - // same object each time for KVO to work at all. Doing this all the time - // requires some odd semantics to avoid reference cycles, so instead we do - // it only to the extent specifically required by KVO. In addition, we - // need to continue to return the same object even if this row is deleted, - // or deleting an object with active observers will explode horribly. - // Once prepareForInvalidation() is called, valueForKey() will always return - // the cached value for object and array properties without checking the - // backing row to verify it's up-to-date. - // - // prepareForInvalidation() must be called on the head of the linked list - // (i.e. on the object pointed to directly by the object schema) - id valueForKey(NSString *key); - - void prepareForInvalidation(); - -private: - // Doubly-linked-list of observed objects for the same row as this - RLMObservationInfo *next = nullptr; - RLMObservationInfo *prev = nullptr; - - // Row being observed - realm::Row row; - RLMClassInfo *objectSchema = nullptr; - - // Object doing the observing - __unsafe_unretained id object = nil; - - // valueForKey: hack - bool invalidated = false; - size_t observerCount = 0; - NSString *lastKey = nil; - __unsafe_unretained RLMProperty *lastProp = nil; - - // objects returned from valueForKey() to keep them alive in case observers - // are added and so that they can still be accessed after row is detached - NSMutableDictionary *cachedObjects; - - void setRow(realm::Table &table, size_t newRow); - - template - void forEach(F&& f) const { - // The user's observation handler may release their last reference to - // the object being observed, which will result in the RLMObservationInfo - // being destroyed. As a result, we need to retain the object which owns - // both `this` and the current info we're looking at. - __attribute__((objc_precise_lifetime)) id self = object, current; - for (auto info = prev; info; info = info->prev) { - current = info->object; - f(info->object); - } - for (auto info = this; info; info = info->next) { - current = info->object; - f(info->object); - } - } - - // Default move/copy constructors don't work due to the intrusive linked - // list and we don't need them - RLMObservationInfo(RLMObservationInfo const&) = delete; - RLMObservationInfo(RLMObservationInfo&&) = delete; - RLMObservationInfo& operator=(RLMObservationInfo const&) = delete; - RLMObservationInfo& operator=(RLMObservationInfo&&) = delete; -}; - -// Get the the observation info chain for the given row -// Will simply return info if it's non-null, and will search ojectSchema's array -// for a matching one otherwise, and return null if there are none -RLMObservationInfo *RLMGetObservationInfo(RLMObservationInfo *info, size_t row, RLMClassInfo& objectSchema); - -// delete all objects from a single table with change notifications -void RLMClearTable(RLMClassInfo &realm); - -// invoke the block, sending notifications for cascading deletes/link nullifications -void RLMTrackDeletions(RLMRealm *realm, dispatch_block_t block); - -std::vector RLMGetObservedRows(RLMSchemaInfo const& schema); -void RLMWillChange(std::vector const& observed, std::vector const& invalidated); -void RLMDidChange(std::vector const& observed, std::vector const& invalidated); diff --git a/Example/Pods/Realm/include/RLMOptionalBase.h b/Example/Pods/Realm/include/RLMOptionalBase.h deleted file mode 100644 index 5ee261e..0000000 --- a/Example/Pods/Realm/include/RLMOptionalBase.h +++ /dev/null @@ -1,38 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 -#import - -NS_ASSUME_NONNULL_BEGIN - -@class RLMObjectBase, RLMProperty; - -@interface RLMOptionalBase : NSProxy - -- (instancetype)init; - -@property (nonatomic, weak) RLMObjectBase *object; - -@property (nonatomic, unsafe_unretained) RLMProperty *property; - -@property (nonatomic, strong, nullable) id underlyingValue; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMPlatform.h b/Example/Pods/Realm/include/RLMPlatform.h deleted file mode 100644 index e69de29..0000000 diff --git a/Example/Pods/Realm/include/RLMPredicateUtil.hpp b/Example/Pods/Realm/include/RLMPredicateUtil.hpp deleted file mode 100644 index 11b8e15..0000000 --- a/Example/Pods/Realm/include/RLMPredicateUtil.hpp +++ /dev/null @@ -1,21 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 - -using ExpressionVisitor = NSExpression *(*)(NSExpression *); -NSPredicate *transformPredicate(NSPredicate *, ExpressionVisitor); diff --git a/Example/Pods/Realm/include/RLMPrefix.h b/Example/Pods/Realm/include/RLMPrefix.h deleted file mode 100644 index df08ce9..0000000 --- a/Example/Pods/Realm/include/RLMPrefix.h +++ /dev/null @@ -1,35 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifdef __OBJC__ -#import -#endif - -#ifdef __cplusplus -#import -#import -#import -#import -#import - -#import -#import -#import -#import -#import -#endif diff --git a/Example/Pods/Realm/include/RLMProperty.h b/Example/Pods/Realm/include/RLMProperty.h deleted file mode 100644 index f19c592..0000000 --- a/Example/Pods/Realm/include/RLMProperty.h +++ /dev/null @@ -1,121 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import - -NS_ASSUME_NONNULL_BEGIN - -/// :nodoc: -@protocol RLMInt -@end - -/// :nodoc: -@protocol RLMBool -@end - -/// :nodoc: -@protocol RLMDouble -@end - -/// :nodoc: -@protocol RLMFloat -@end - -/// :nodoc: -@interface NSNumber () -@end - -/** - `RLMProperty` instances represent properties managed by a Realm in the context of an object schema. Such properties may - be persisted to a Realm file or computed from other data from the Realm. - - When using Realm, `RLMProperty` instances allow performing migrations and introspecting the database's schema. - - These property instances map to columns in the core database. - */ -@interface RLMProperty : NSObject - -#pragma mark - Properties - -/** - The name of the property. - */ -@property (nonatomic, readonly) NSString *name; - -/** - The type of the property. - - @see `RLMPropertyType` - */ -@property (nonatomic, readonly) RLMPropertyType type; - -/** - Indicates whether this property is indexed. - - @see `RLMObject` - */ -@property (nonatomic, readonly) BOOL indexed; - -/** - For `RLMObject` and `RLMArray` properties, the name of the class of object stored in the property. - */ -@property (nonatomic, readonly, copy, nullable) NSString *objectClassName; - -/** - For linking objects properties, the property name of the property the linking objects property is linked to. - */ -@property (nonatomic, readonly, copy, nullable) NSString *linkOriginPropertyName; - -/** - Indicates whether this property is optional. - */ -@property (nonatomic, readonly) BOOL optional; - -#pragma mark - Methods - -/** - Returns whether a given property object is equal to the receiver. - */ -- (BOOL)isEqualToProperty:(RLMProperty *)property; - -@end - - -/** - An `RLMPropertyDescriptor` instance represents a specific property on a given class. - */ -@interface RLMPropertyDescriptor : NSObject - -/** - Creates and returns a property descriptor. - - @param objectClass The class of this property descriptor. - @param propertyName The name of this property descriptor. - */ -+ (instancetype)descriptorWithClass:(Class)objectClass propertyName:(NSString *)propertyName; - -/// The class of the property. -@property (nonatomic, readonly) Class objectClass; - -/// The name of the property. -@property (nonatomic, readonly) NSString *propertyName; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMProperty_Private.h b/Example/Pods/Realm/include/RLMProperty_Private.h deleted file mode 100644 index d36f978..0000000 --- a/Example/Pods/Realm/include/RLMProperty_Private.h +++ /dev/null @@ -1,111 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import - -@class RLMObjectBase; - -NS_ASSUME_NONNULL_BEGIN - -BOOL RLMPropertyTypeIsNullable(RLMPropertyType propertyType); -BOOL RLMPropertyTypeIsComputed(RLMPropertyType propertyType); - -// private property interface -@interface RLMProperty () { -@public - RLMPropertyType _type; - Ivar _swiftIvar; -} - -- (instancetype)initWithName:(NSString *)name - indexed:(BOOL)indexed - linkPropertyDescriptor:(nullable RLMPropertyDescriptor *)linkPropertyDescriptor - property:(objc_property_t)property; - -- (instancetype)initSwiftPropertyWithName:(NSString *)name - indexed:(BOOL)indexed - linkPropertyDescriptor:(nullable RLMPropertyDescriptor *)linkPropertyDescriptor - property:(objc_property_t)property - instance:(RLMObjectBase *)objectInstance; - -- (instancetype)initSwiftListPropertyWithName:(NSString *)name - ivar:(Ivar)ivar - objectClassName:(nullable NSString *)objectClassName; - -- (instancetype)initSwiftOptionalPropertyWithName:(NSString *)name - indexed:(BOOL)indexed - ivar:(Ivar)ivar - propertyType:(RLMPropertyType)propertyType; - -- (instancetype)initSwiftLinkingObjectsPropertyWithName:(NSString *)name - ivar:(Ivar)ivar - objectClassName:(nullable NSString *)objectClassName - linkOriginPropertyName:(nullable NSString *)linkOriginPropertyName; - -// private setters -@property (nonatomic, readwrite) NSString *name; -@property (nonatomic, readwrite, assign) RLMPropertyType type; -@property (nonatomic, readwrite) BOOL indexed; -@property (nonatomic, readwrite) BOOL optional; -@property (nonatomic, copy, nullable) NSString *objectClassName; - -// private properties -@property (nonatomic, assign) NSUInteger index; -@property (nonatomic, assign) char objcType; -@property (nonatomic, copy) NSString *objcRawType; -@property (nonatomic, assign) BOOL isPrimary; -@property (nonatomic, assign) Ivar swiftIvar; - -// getter and setter names -@property (nonatomic, copy) NSString *getterName; -@property (nonatomic, copy) NSString *setterName; -@property (nonatomic) SEL getterSel; -@property (nonatomic) SEL setterSel; - -- (RLMProperty *)copyWithNewName:(NSString *)name; - -@end - -@interface RLMProperty (Dynamic) -/** - This method is useful only in specialized circumstances, for example, in conjunction with - +[RLMObjectSchema initWithClassName:objectClass:properties:]. If you are simply building an - app on Realm, it is not recommened to use this method. - - Initialize an RLMProperty - - @warning This method is useful only in specialized circumstances. - - @param name The property name. - @param type The property type. - @param objectClassName The object type used for Object and Array types. - @param linkOriginPropertyName The property name of the origin of a link. Used for linking objects properties. - - @return An initialized instance of RLMProperty. - */ -- (instancetype)initWithName:(NSString *)name - type:(RLMPropertyType)type - objectClassName:(nullable NSString *)objectClassName - linkOriginPropertyName:(nullable NSString *)linkOriginPropertyName - indexed:(BOOL)indexed - optional:(BOOL)optional; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMProperty_Private.hpp b/Example/Pods/Realm/include/RLMProperty_Private.hpp deleted file mode 100644 index 0e214d5..0000000 --- a/Example/Pods/Realm/include/RLMProperty_Private.hpp +++ /dev/null @@ -1,29 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "property.hpp" - -@interface RLMProperty () - -+ (instancetype)propertyForObjectStoreProperty:(const realm::Property&)property; - -- (realm::Property)objectStoreCopy; - -@end diff --git a/Example/Pods/Realm/include/RLMQueryUtil.hpp b/Example/Pods/Realm/include/RLMQueryUtil.hpp deleted file mode 100644 index ce31c70..0000000 --- a/Example/Pods/Realm/include/RLMQueryUtil.hpp +++ /dev/null @@ -1,42 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import - -namespace realm { - class Group; - class Query; - class SortDescriptor; - class Table; -} - -@class RLMObjectSchema, RLMProperty, RLMSchema, RLMSortDescriptor; - -extern NSString * const RLMPropertiesComparisonTypeMismatchException; -extern NSString * const RLMUnsupportedTypesFoundInPropertyComparisonException; - -realm::Query RLMPredicateToQuery(NSPredicate *predicate, RLMObjectSchema *objectSchema, - RLMSchema *schema, realm::Group &group); - -// return property - throw for invalid column name -RLMProperty *RLMValidatedProperty(RLMObjectSchema *objectSchema, NSString *columnName); - -// validate the array of RLMSortDescriptors and convert it to a realm::SortDescriptor -realm::SortDescriptor RLMSortDescriptorFromDescriptors(realm::Table& table, NSArray *descriptors); diff --git a/Example/Pods/Realm/include/RLMRealm.h b/Example/Pods/Realm/include/RLMRealm.h deleted file mode 100644 index b251b73..0000000 --- a/Example/Pods/Realm/include/RLMRealm.h +++ /dev/null @@ -1,582 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import "RLMConstants.h" - -@class RLMRealmConfiguration, RLMObject, RLMSchema, RLMMigration, RLMNotificationToken; - -NS_ASSUME_NONNULL_BEGIN - -/** - An `RLMRealm` instance (also referred to as "a Realm") represents a Realm - database. - - Realms can either be stored on disk (see `+[RLMRealm realmWithURL:]`) or in - memory (see `RLMRealmConfiguration`). - - `RLMRealm` instances are cached internally, and constructing equivalent `RLMRealm` - objects (for example, by using the same path or identifier) multiple times on a single thread - within a single iteration of the run loop will normally return the same - `RLMRealm` object. - - If you specifically want to ensure an `RLMRealm` instance is - destroyed (for example, if you wish to open a Realm, check some property, and - then possibly delete the Realm file and re-open it), place the code which uses - the Realm within an `@autoreleasepool {}` and ensure you have no other - strong references to it. - - @warning `RLMRealm` instances are not thread safe and cannot be shared across - threads or dispatch queues. Trying to do so will cause an exception to be thrown. - You must call this method on each thread you want - to interact with the Realm on. For dispatch queues, this means that you must - call it in each block which is dispatched, as a queue is not guaranteed to run - all of its blocks on the same thread. - */ - -@interface RLMRealm : NSObject - -#pragma mark - Creating & Initializing a Realm - -/** - Obtains an instance of the default Realm. - - The default Realm is used by the `RLMObject` class methods - which do not take an `RLMRealm` parameter, but is otherwise not special. The - default Realm is persisted as *default.realm* under the *Documents* directory of - your Application on iOS, and in your application's *Application Support* - directory on OS X. - - The default Realm is created using the default `RLMRealmConfiguration`, which - can be changed via `+[RLMRealmConfiguration setDefaultConfiguration:]`. - - @return The default `RLMRealm` instance for the current thread. - */ -+ (instancetype)defaultRealm; - -/** - Obtains an `RLMRealm` instance with the given configuration. - - @param configuration A configuration object to use when creating the Realm. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return An `RLMRealm` instance. - */ -+ (nullable instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error; - -/** - Obtains an `RLMRealm` instance persisted at a specified file URL. - - @param fileURL The local URL of the file the Realm should be saved at. - - @return An `RLMRealm` instance. - */ -+ (instancetype)realmWithURL:(NSURL *)fileURL; - -/** - The `RLMSchema` used by the Realm. - */ -@property (nonatomic, readonly) RLMSchema *schema; - -/** - Indicates if the Realm is currently engaged in a write transaction. - - @warning Do not simply check this property and then start a write transaction whenever an object needs to be - created, updated, or removed. Doing so might cause a large number of write transactions to be created, - degrading performance. Instead, always prefer performing multiple updates during a single transaction. - */ -@property (nonatomic, readonly) BOOL inWriteTransaction; - -/** - The `RLMRealmConfiguration` object that was used to create this `RLMRealm` instance. - */ -@property (nonatomic, readonly) RLMRealmConfiguration *configuration; - -/** - Indicates if this Realm contains any objects. - */ -@property (nonatomic, readonly) BOOL isEmpty; - -#pragma mark - Notifications - -/** - The type of a block to run whenever the data within the Realm is modified. - - @see `-[RLMRealm addNotificationBlock:]` - */ -typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *realm); - -#pragma mark - Receiving Notification when a Realm Changes - -/** - Adds a notification handler for changes in this Realm, and returns a notification token. - - Notification handlers are called after each write transaction is committed, - either on the current thread or other threads. - - Handler blocks are called on the same thread that they were added on, and may - only be added on threads which are currently within a run loop. Unless you are - specifically creating and running a run loop on a background thread, this will - normally only be the main thread. - - The block has the following definition: - - typedef void(^RLMNotificationBlock)(RLMNotification notification, RLMRealm *realm); - - It receives the following parameters: - - - `NSString` \***notification**: The name of the incoming notification. See - `RLMRealmNotification` for information on what - notifications are sent. - - `RLMRealm` \***realm**: The Realm for which this notification occurred. - - @param block A block which is called to process Realm notifications. - - @return A token object which must be retained as long as you wish to continue - receiving change notifications. - */ -- (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block __attribute__((warn_unused_result)); - -#pragma mark - Transactions - - -#pragma mark - Writing to a Realm - -/** - Begins a write transaction on the Realm. - - Only one write transaction can be open at a time for each Realm file. Write - transactions cannot be nested, and trying to begin a write transaction on a - Realm which is already in a write transaction will throw an exception. Calls to - `beginWriteTransaction` from `RLMRealm` instances for the same Realm file in - other threads or other processes will block until the current write transaction - completes or is cancelled. - - Before beginning the write transaction, `beginWriteTransaction` updates the - `RLMRealm` instance to the latest Realm version, as if `refresh` had been - called, and generates notifications if applicable. This has no effect if the - Realm was already up to date. - - It is rarely a good idea to have write transactions span multiple cycles of - the run loop, but if you do wish to do so you will need to ensure that the - Realm participating in the write transaction is kept alive until the write - transaction is committed. - */ -- (void)beginWriteTransaction; - -/** - Commits all write operations in the current write transaction, and ends the - transaction. - - After saving the changes, all notification blocks registered on this specific - `RLMRealm` instance are invoked synchronously. Notification blocks registered - on other threads or on collections are invoked asynchronously. If you do not - want to receive a specific notification for this write tranaction, see - `commitWriteTransactionWithoutNotifying:error:`. - - This method can fail if there is insufficient disk space available to save the - writes made, or due to unexpected i/o errors. This version of the method throws - an exception when errors occur. Use the version with a `NSError` out parameter - instead if you wish to handle errors. - - @warning This method may only be called during a write transaction. - */ -- (void)commitWriteTransaction NS_SWIFT_UNAVAILABLE(""); - -/** - Commits all write operations in the current write transaction, and ends the - transaction. - - After saving the changes, all notification blocks registered on this specific - `RLMRealm` instance are invoked synchronously. Notification blocks registered - on other threads or on collections are invoked asynchronously. If you do not - want to receive a specific notification for this write tranaction, see - `commitWriteTransactionWithoutNotifying:error:`. - - This method can fail if there is insufficient disk space available to save the - writes made, or due to unexpected i/o errors. - - @warning This method may only be called during a write transaction. - - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return Whether the transaction succeeded. - */ -- (BOOL)commitWriteTransaction:(NSError **)error; - -/** - Commits all write operations in the current write transaction, without - notifying specific notification blocks of the changes. - - After saving the changes, all notification blocks registered on this specific - `RLMRealm` instance are invoked synchronously. Notification blocks registered - on other threads or on collections are scheduled to be invoked asynchronously. - - You can skip notifiying specific notification blocks about the changes made - in this write transaction by passing in their associated notification tokens. - This is primarily useful when the write transaction is saving changes already - made in the UI and you do not want to have the notification block attempt to - re-apply the same changes. - - The tokens passed to this method must be for notifications for this specific - `RLMRealm` instance. Notifications for different threads cannot be skipped - using this method. - - This method can fail if there is insufficient disk space available to save the - writes made, or due to unexpected i/o errors. - - @warning This method may only be called during a write transaction. - - @param tokens An array of notification tokens which were returned from adding - callbacks which you do not want to be notified for the changes - made in this write transaction. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return Whether the transaction succeeded. - */ -- (BOOL)commitWriteTransactionWithoutNotifying:(NSArray *)tokens error:(NSError **)error; - -/** - Reverts all writes made during the current write transaction and ends the transaction. - - This rolls back all objects in the Realm to the state they were in at the - beginning of the write transaction, and then ends the transaction. - - This restores the data for deleted objects, but does not revive invalidated - object instances. Any `RLMObject`s which were added to the Realm will be - invalidated rather than becoming unmanaged. - Given the following code: - - ObjectType *oldObject = [[ObjectType objectsWhere:@"..."] firstObject]; - ObjectType *newObject = [[ObjectType alloc] init]; - - [realm beginWriteTransaction]; - [realm addObject:newObject]; - [realm deleteObject:oldObject]; - [realm cancelWriteTransaction]; - - Both `oldObject` and `newObject` will return `YES` for `isInvalidated`, - but re-running the query which provided `oldObject` will once again return - the valid object. - - KVO observers on any objects which were modified during the transaction will - be notified about the change back to their initial values, but no other - notifcations are produced by a cancelled write transaction. - - @warning This method may only be called during a write transaction. - */ -- (void)cancelWriteTransaction; - -/** - Performs actions contained within the given block inside a write transaction. - - @see `[RLMRealm transactionWithBlock:error:]` - */ -- (void)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block NS_SWIFT_UNAVAILABLE(""); - -/** - Performs actions contained within the given block inside a write transaction. - - Write transactions cannot be nested, and trying to execute a write transaction - on a Realm which is already participating in a write transaction will throw an - exception. Calls to `transactionWithBlock:` from `RLMRealm` instances in other - threads will block until the current write transaction completes. - - Before beginning the write transaction, `transactionWithBlock:` updates the - `RLMRealm` instance to the latest Realm version, as if `refresh` had been called, and - generates notifications if applicable. This has no effect if the Realm - was already up to date. - - @param block The block containing actions to perform. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return Whether the transaction succeeded. - */ -- (BOOL)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block error:(NSError **)error; - -/** - Updates the Realm and outstanding objects managed by the Realm to point to the - most recent data. - - If the version of the Realm is actually changed, Realm and collection - notifications will be sent to reflect the changes. This may take some time, as - collection notifications are prepared on a background thread. As a result, - calling this method on the main thread is not advisable. - - @return Whether there were any updates for the Realm. Note that `YES` may be - returned even if no data actually changed. - */ -- (BOOL)refresh; - -/** - Set this property to `YES` to automatically update this Realm when changes - happen in other threads. - - If set to `YES` (the default), changes made on other threads will be reflected - in this Realm on the next cycle of the run loop after the changes are - committed. If set to `NO`, you must manually call `-refresh` on the Realm to - update it to get the latest data. - - Note that by default, background threads do not have an active run loop and you - will need to manually call `-refresh` in order to update to the latest version, - even if `autorefresh` is set to `YES`. - - Even with this property enabled, you can still call `-refresh` at any time to - update the Realm before the automatic refresh would occur. - - Write transactions will still always advance a Realm to the latest version and - produce local notifications on commit even if autorefresh is disabled. - - Disabling `autorefresh` on a Realm without any strong references to it will not - have any effect, and `autorefresh` will revert back to `YES` the next time the - Realm is created. This is normally irrelevant as it means that there is nothing - to refresh (as managed `RLMObject`s, `RLMArray`s, and `RLMResults` have strong - references to the Realm that manages them), but it means that setting - `RLMRealm.defaultRealm.autorefresh = NO` in - `application:didFinishLaunchingWithOptions:` and only later storing Realm - objects will not work. - - Defaults to `YES`. - */ -@property (nonatomic) BOOL autorefresh; - -/** - Writes a compacted and optionally encrypted copy of the Realm to the given local URL. - - The destination file cannot already exist. - - Note that if this method is called from within a write transaction, the - *current* data is written, not the data from the point when the previous write - transaction was committed. - - @param fileURL Local URL to save the Realm to. - @param key Optional 64-byte encryption key to encrypt the new file with. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return `YES` if the Realm was successfully written to disk, `NO` if an error occurred. -*/ -- (BOOL)writeCopyToURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error; - -/** - Invalidates all `RLMObject`s, `RLMResults`, `RLMLinkingObjects`, and `RLMArray`s managed by the Realm. - - A Realm holds a read lock on the version of the data accessed by it, so - that changes made to the Realm on different threads do not modify or delete the - data seen by this Realm. Calling this method releases the read lock, - allowing the space used on disk to be reused by later write transactions rather - than growing the file. This method should be called before performing long - blocking operations on a background thread on which you previously read data - from the Realm which you no longer need. - - All `RLMObject`, `RLMResults` and `RLMArray` instances obtained from this - `RLMRealm` instance on the current thread are invalidated. `RLMObject`s and `RLMArray`s - cannot be used. `RLMResults` will become empty. The Realm itself remains valid, - and a new read transaction is implicitly begun the next time data is read from the Realm. - - Calling this method multiple times in a row without reading any data from the - Realm, or before ever reading any data from the Realm, is a no-op. This method - may not be called on a read-only Realm. - */ -- (void)invalidate; - -#pragma mark - Accessing Objects - - -#pragma mark - Adding and Removing Objects from a Realm - -/** - Adds an object to the Realm. - - Once added, this object is considered to be managed by the Realm. It can be retrieved - using the `objectsWhere:` selectors on `RLMRealm` and on subclasses of `RLMObject`. - - When added, all child relationships referenced by this object will also be added to - the Realm if they are not already in it. - - If the object or any related objects are already being managed by a different Realm - an exception will be thrown. Use `-[RLMObject createInRealm:withObject:]` to insert a copy of a managed object - into a different Realm. - - The object to be added must be valid and cannot have been previously deleted - from a Realm (i.e. `isInvalidated` must be `NO`). - - @warning This method may only be called during a write transaction. - - @param object The object to be added to this Realm. - */ -- (void)addObject:(RLMObject *)object; - -/** - Adds all the objects in a collection to the Realm. - - This is the equivalent of calling `addObject:` for every object in a collection. - - @warning This method may only be called during a write transaction. - - @param array An enumerable object such as `NSArray` or `RLMResults` which contains objects to be added to - the Realm. - - @see `addObject:` - */ -- (void)addObjects:(id)array; - -/** - Adds or updates an existing object into the Realm. - - The object provided must have a designated primary key. If no objects exist in the Realm - with the same primary key value, the object is inserted. Otherwise, the existing object is - updated with any changed values. - - As with `addObject:`, the object cannot already be managed by a different - Realm. Use `-[RLMObject createOrUpdateInRealm:withValue:]` to copy values to - a different Realm. - - @warning This method may only be called during a write transaction. - - @param object The object to be added or updated. - */ -- (void)addOrUpdateObject:(RLMObject *)object; - -/** - Adds or updates all the objects in a collection into the Realm. - - This is the equivalent of calling `addOrUpdateObject:` for every object in a collection. - - @warning This method may only be called during a write transaction. - - @param array An `NSArray`, `RLMArray`, or `RLMResults` of `RLMObject`s (or subclasses) to be added to the Realm. - - @see `addOrUpdateObject:` - */ -- (void)addOrUpdateObjectsFromArray:(id)array; - -/** - Deletes an object from the Realm. Once the object is deleted it is considered invalidated. - - @warning This method may only be called during a write transaction. - - @param object The object to be deleted. - */ -- (void)deleteObject:(RLMObject *)object; - -/** - Deletes one or more objects from the Realm. - - This is the equivalent of calling `deleteObject:` for every object in a collection. - - @warning This method may only be called during a write transaction. - - @param array An `RLMArray`, `NSArray`, or `RLMResults` of `RLMObject`s (or subclasses) to be deleted. - - @see `deleteObject:` - */ -- (void)deleteObjects:(id)array; - -/** - Deletes all objects from the Realm. - - @warning This method may only be called during a write transaction. - - @see `deleteObject:` - */ -- (void)deleteAllObjects; - - -#pragma mark - Migrations - -/** - The type of a migration block used to migrate a Realm. - - @param migration A `RLMMigration` object used to perform the migration. The - migration object allows you to enumerate and alter any - existing objects which require migration. - - @param oldSchemaVersion The schema version of the Realm being migrated. - */ -typedef void (^RLMMigrationBlock)(RLMMigration *migration, uint64_t oldSchemaVersion); - -/** - Returns the schema version for a Realm at a given local URL. - - @param fileURL Local URL to a Realm file. - @param key 64-byte key used to encrypt the file, or `nil` if it is unencrypted. - @param error If an error occurs, upon return contains an `NSError` object - that describes the problem. If you are not interested in - possible errors, pass in `NULL`. - - @return The version of the Realm at `fileURL`, or `RLMNotVersioned` if the version cannot be read. - */ -+ (uint64_t)schemaVersionAtURL:(NSURL *)fileURL encryptionKey:(nullable NSData *)key error:(NSError **)error -NS_REFINED_FOR_SWIFT; - -/** - Performs the given Realm configuration's migration block on a Realm at the given path. - - This method is called automatically when opening a Realm for the first time and does - not need to be called explicitly. You can choose to call this method to control - exactly when and how migrations are performed. - - @param configuration The Realm configuration used to open and migrate the Realm. - @return The error that occurred while applying the migration, if any. - - @see RLMMigration - */ -+ (nullable NSError *)migrateRealm:(RLMRealmConfiguration *)configuration -__deprecated_msg("Use `performMigrationForConfiguration:error:`") NS_REFINED_FOR_SWIFT; - -/** - Performs the given Realm configuration's migration block on a Realm at the given path. - - This method is called automatically when opening a Realm for the first time and does - not need to be called explicitly. You can choose to call this method to control - exactly when and how migrations are performed. - - @param configuration The Realm configuration used to open and migrate the Realm. - @return The error that occurred while applying the migration, if any. - - @see RLMMigration - */ -+ (BOOL)performMigrationForConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error; - -@end - -/** - A token which is returned from methods which subscribe to changes to a Realm. - - Change subscriptions in Realm return an `RLMNotificationToken` instance, - which can be used to unsubscribe from the changes. You must store a strong - reference to the token for as long as you want to continue to receive notifications. - When you wish to stop, call the `-stop` method. Notifications are also stopped if - the token is deallocated. - */ -@interface RLMNotificationToken : NSObject -/// Stops notifications for the change subscription that returned this token. -- (void)stop; -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMRealmConfiguration+Sync.h b/Example/Pods/Realm/include/RLMRealmConfiguration+Sync.h deleted file mode 100644 index 2a7aca5..0000000 --- a/Example/Pods/Realm/include/RLMRealmConfiguration+Sync.h +++ /dev/null @@ -1,42 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil.h" - -@class RLMSyncConfiguration; - -/// :nodoc: -@interface RLMRealmConfiguration (Sync) - -NS_ASSUME_NONNULL_BEGIN - -/** - A configuration object representing configuration state for Realms intended to sync with a Realm Object Server. - - This property is mutually exclusive with both `inMemoryIdentifier` and `fileURL`; setting one will nil out the other - two. - - @see `RLMSyncConfiguration` - */ -@property (nullable, nonatomic) RLMSyncConfiguration *syncConfiguration; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMRealmConfiguration.h b/Example/Pods/Realm/include/RLMRealmConfiguration.h deleted file mode 100644 index 21e163b..0000000 --- a/Example/Pods/Realm/include/RLMRealmConfiguration.h +++ /dev/null @@ -1,99 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - An `RLMRealmConfiguration` instance describes the different options used to - create an instance of a Realm. - - `RLMRealmConfiguration` instances are just plain `NSObject`s. Unlike `RLMRealm`s - and `RLMObject`s, they can be freely shared between threads as long as you do not - mutate them. - - Creating configuration objects for class subsets (by setting the - `objectClasses` property) can be expensive. Because of this, you will normally want to - cache and reuse a single configuration object for each distinct configuration rather than - creating a new object each time you open a Realm. - */ -@interface RLMRealmConfiguration : NSObject - -#pragma mark - Default Configuration - -/** - Returns the default configuration used to create Realms when no other - configuration is explicitly specified (i.e. `+[RLMRealm defaultRealm]`). - - @return The default Realm configuration. - */ -+ (instancetype)defaultConfiguration; - -/** - Sets the default configuration to the given `RLMRealmConfiguration`. - - @param configuration The new default Realm configuration. - */ -+ (void)setDefaultConfiguration:(RLMRealmConfiguration *)configuration; - -#pragma mark - Properties - -/// The local URL of the Realm file. Mutually exclusive with `inMemoryIdentifier`. -@property (nonatomic, copy, nullable) NSURL *fileURL; - -/// A string used to identify a particular in-memory Realm. Mutually exclusive with `fileURL`. -@property (nonatomic, copy, nullable) NSString *inMemoryIdentifier; - -/// A 64-byte key to use to encrypt the data, or `nil` if encryption is not enabled. -@property (nonatomic, copy, nullable) NSData *encryptionKey; - -/// Whether to open the Realm in read-only mode. -/// -/// This is required to be able to open Realm files which are not writeable or -/// are in a directory which is not writeable. This should only be used on files -/// which will not be modified by anyone while they are open, and not just to -/// get a read-only view of a file which may be written to by another thread or -/// process. Opening in read-only mode requires disabling Realm's reader/writer -/// coordination, so committing a write transaction from another process will -/// result in crashes. -@property (nonatomic) BOOL readOnly; - -/// The current schema version. -@property (nonatomic) uint64_t schemaVersion; - -/// The block which migrates the Realm to the current version. -@property (nonatomic, copy, nullable) RLMMigrationBlock migrationBlock; - -/** - Whether to recreate the Realm file with the provided schema if a migration is required. - This is the case when the stored schema differs from the provided schema or - the stored schema version differs from the version on this configuration. - Setting this property to `YES` deletes the file if a migration would otherwise be required or executed. - - @note Setting this property to `YES` doesn't disable file format migrations. - */ -@property (nonatomic) BOOL deleteRealmIfMigrationNeeded; - -/// The classes managed by the Realm. -@property (nonatomic, copy, nullable) NSArray *objectClasses; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMRealmConfiguration_Private.h b/Example/Pods/Realm/include/RLMRealmConfiguration_Private.h deleted file mode 100644 index 7581af1..0000000 --- a/Example/Pods/Realm/include/RLMRealmConfiguration_Private.h +++ /dev/null @@ -1,42 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 - -@class RLMSchema; - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMRealmConfiguration () - -@property (nonatomic, readwrite) bool cache; -@property (nonatomic, readwrite) bool dynamic; -@property (nonatomic, readwrite) bool disableFormatUpgrade; -@property (nonatomic, copy, nullable) RLMSchema *customSchema; - -// Get the default confiugration without copying it -+ (RLMRealmConfiguration *)rawDefaultConfiguration; - -+ (void)resetRealmConfigurationState; -@end - -// Get a path in the platform-appropriate documents directory with the given filename -FOUNDATION_EXTERN NSString *RLMRealmPathForFile(NSString *fileName); -FOUNDATION_EXTERN NSString *RLMRealmPathForFileAndBundleIdentifier(NSString *fileName, NSString *mainBundleIdentifier); - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMRealmConfiguration_Private.hpp b/Example/Pods/Realm/include/RLMRealmConfiguration_Private.hpp deleted file mode 100644 index a89fb0f..0000000 --- a/Example/Pods/Realm/include/RLMRealmConfiguration_Private.hpp +++ /dev/null @@ -1,26 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "shared_realm.hpp" - -@interface RLMRealmConfiguration () -- (realm::Realm::Config&)config; - -@property (nonatomic) realm::SchemaMode schemaMode; -@end diff --git a/Example/Pods/Realm/include/RLMRealmUtil.hpp b/Example/Pods/Realm/include/RLMRealmUtil.hpp deleted file mode 100644 index 36dbc84..0000000 --- a/Example/Pods/Realm/include/RLMRealmUtil.hpp +++ /dev/null @@ -1,38 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import -#import - -@class RLMRealm; - -namespace realm { - class BindingContext; -} - -// Add a Realm to the weak cache -void RLMCacheRealm(std::string const& path, RLMRealm *realm); -// Get a Realm for the given path which can be used on the current thread -RLMRealm *RLMGetThreadLocalCachedRealmForPath(std::string const& path); -// Get a Realm for the given path -RLMRealm *RLMGetAnyCachedRealmForPath(std::string const& path); -// Clear the weak cache of Realms -void RLMClearRealmCache(); - -std::unique_ptr RLMCreateBindingContext(RLMRealm *realm); diff --git a/Example/Pods/Realm/include/RLMRealm_Dynamic.h b/Example/Pods/Realm/include/RLMRealm_Dynamic.h deleted file mode 100644 index 3a26f49..0000000 --- a/Example/Pods/Realm/include/RLMRealm_Dynamic.h +++ /dev/null @@ -1,118 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import -#import - -@class RLMResults; - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMRealm (Dynamic) - -#pragma mark - Getting Objects from a Realm - -/** - Returns all objects of a given type from the Realm. - - @warning This method is useful only in specialized circumstances, for example, when building components - that integrate with Realm. The preferred way to get objects of a single class is to use the class - methods on `RLMObject`. - - @param className The name of the `RLMObject` subclass to retrieve on (e.g. `MyClass.className`). - - @return An `RLMResults` containing all objects in the Realm of the given type. - - @see `+[RLMObject allObjects]` - */ -- (RLMResults *)allObjects:(NSString *)className; - -/** - Returns all objects matching the given predicate from the Realm. - - @warning This method is useful only in specialized circumstances, for example, when building components - that integrate with Realm. The preferred way to get objects of a single class is to use the class - methods on `RLMObject`. - - @param className The type of objects you are looking for (name of the class). - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return An `RLMResults` containing results matching the given predicate. - - @see `+[RLMObject objectsWhere:]` - */ -- (RLMResults *)objects:(NSString *)className where:(NSString *)predicateFormat, ...; - -/** - Returns all objects matching the given predicate from the Realm. - - @warning This method is useful only in specialized circumstances, for example, when building components - that integrate with Realm. The preferred way to get objects of a single class is to use the class - methods on `RLMObject`. - - @param className The type of objects you are looking for (name of the class). - @param predicate The predicate with which to filter the objects. - - @return An `RLMResults` containing results matching the given predicate. - - @see `+[RLMObject objectsWhere:]` - */ -- (RLMResults *)objects:(NSString *)className withPredicate:(NSPredicate *)predicate; - -/** - Returns the object of the given type with the given primary key from the Realm. - - @warning This method is useful only in specialized circumstances, for example, when building components - that integrate with Realm. The preferred way to get an object of a single class is to use the class - methods on `RLMObject`. - - @param className The class name for the object you are looking for. - @param primaryKey The primary key value for the object you are looking for. - - @return An object, or `nil` if an object with the given primary key does not exist. - - @see `+[RLMObject objectForPrimaryKey:]` - */ -- (nullable RLMObject *)objectWithClassName:(NSString *)className forPrimaryKey:(id)primaryKey; - -/** - Creates an `RLMObject` instance of type `className` in the Realm, and populates it using a given object. - - The `value` argument is used to populate the object. It can be a key-value coding compliant object, an array or - dictionary returned from the methods in `NSJSONSerialization`, or an array containing one element for each managed - property. An exception will be thrown if any required properties are not present and those properties were not defined - with default values. - - When passing in an array as the `value` argument, all properties must be present, valid and in the same order as the - properties defined in the model. - - @warning This method is useful only in specialized circumstances, for example, when building components - that integrate with Realm. If you are simply building an app on Realm, it is recommended to - use `[RLMObject createInDefaultRealmWithValue:]`. - - @param value The value used to populate the object. - - @return An `RLMObject` instance of type `className`. - */ --(RLMObject *)createObject:(NSString *)className withValue:(id)value; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMRealm_Private.h b/Example/Pods/Realm/include/RLMRealm_Private.h deleted file mode 100644 index c8ca2d2..0000000 --- a/Example/Pods/Realm/include/RLMRealm_Private.h +++ /dev/null @@ -1,52 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -@class RLMFastEnumerator; - -NS_ASSUME_NONNULL_BEGIN - -// Disable syncing files to disk. Cannot be re-enabled. Use only for tests. -FOUNDATION_EXTERN void RLMDisableSyncToDisk(); - -FOUNDATION_EXTERN NSData * _Nullable RLMRealmValidatedEncryptionKey(NSData *key); - -// Translate an in-flight exception resulting from opening a SharedGroup to -// an NSError or NSException (if error is nil) -void RLMRealmTranslateException(NSError **error); - -// RLMRealm private members -@interface RLMRealm () - -@property (nonatomic, readonly) BOOL dynamic; -@property (nonatomic, readwrite) RLMSchema *schema; - -+ (void)resetRealmState; - -- (void)registerEnumerator:(RLMFastEnumerator *)enumerator; -- (void)unregisterEnumerator:(RLMFastEnumerator *)enumerator; -- (void)detachAllEnumerators; - -- (void)sendNotifications:(RLMNotification)notification; -- (void)verifyThread; -- (void)verifyNotificationsAreSupported; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMRealm_Private.hpp b/Example/Pods/Realm/include/RLMRealm_Private.hpp deleted file mode 100644 index a1bb294..0000000 --- a/Example/Pods/Realm/include/RLMRealm_Private.hpp +++ /dev/null @@ -1,36 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 "RLMRealm_Private.h" - -#import "RLMClassInfo.hpp" - -namespace realm { - class Group; - class Realm; -} - -@interface RLMRealm () { - @public - std::shared_ptr _realm; - RLMSchemaInfo _info; -} - -// FIXME - group should not be exposed -@property (nonatomic, readonly) realm::Group &group; -@end diff --git a/Example/Pods/Realm/include/RLMResults.h b/Example/Pods/Realm/include/RLMResults.h deleted file mode 100644 index 82ff20c..0000000 --- a/Example/Pods/Realm/include/RLMResults.h +++ /dev/null @@ -1,332 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import - -NS_ASSUME_NONNULL_BEGIN - -@class RLMObject, RLMRealm, RLMNotificationToken; - -/** - `RLMResults` is an auto-updating container type in Realm returned from object - queries. It represents the results of the query in the form of a collection of objects. - - `RLMResults` can be queried using the same predicates as `RLMObject` and `RLMArray`, - and you can chain queries to further filter results. - - `RLMResults` always reflect the current state of the Realm on the current thread, - including during write transactions on the current thread. The one exception to - this is when using `for...in` fast enumeration, which will always enumerate - over the objects which matched the query when the enumeration is begun, even if - some of them are deleted or modified to be excluded by the filter during the - enumeration. - - `RLMResults` are lazily evaluated the first time they are accessed; they only - run queries when the result of the query is requested. This means that - chaining several temporary `RLMResults` to sort and filter your data does not - perform any extra work processing the intermediate state. - - Once the results have been evaluated or a notification block has been added, - the results are eagerly kept up-to-date, with the work done to keep them - up-to-date done on a background thread whenever possible. - - `RLMResults` cannot be directly instantiated. - */ -@interface RLMResults : NSObject - -#pragma mark - Properties - -/** - The number of objects in the results collection. - */ -@property (nonatomic, readonly, assign) NSUInteger count; - -/** - The class name (i.e. type) of the `RLMObject`s contained in the results collection. - */ -@property (nonatomic, readonly, copy) NSString *objectClassName; - -/** - The Realm which manages this results collection. - */ -@property (nonatomic, readonly) RLMRealm *realm; - -/** - Indicates if the results collection is no longer valid. - - The results collection becomes invalid if `invalidate` is called on the containing `realm`. - An invalidated results collection can be accessed, but will always be empty. - */ -@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated; - -#pragma mark - Accessing Objects from an RLMResults - -/** - Returns the object at the index specified. - - @param index The index to look up. - - @return An `RLMObject` of the type contained in the results collection. - */ -- (RLMObjectType)objectAtIndex:(NSUInteger)index; - -/** - Returns the first object in the results collection. - - Returns `nil` if called on an empty results collection. - - @return An `RLMObject` of the type contained in the results collection. - */ -- (nullable RLMObjectType)firstObject; - -/** - Returns the last object in the results collection. - - Returns `nil` if called on an empty results collection. - - @return An `RLMObject` of the type contained in the results collection. - */ -- (nullable RLMObjectType)lastObject; - -#pragma mark - Querying Results - -/** - Returns the index of an object in the results collection. - - Returns `NSNotFound` if the object is not found in the results collection. - - @param object An object (of the same type as returned from the `objectClassName` selector). - */ -- (NSUInteger)indexOfObject:(RLMObjectType)object; - -/** - Returns the index of the first object in the results collection matching the predicate. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return The index of the object, or `NSNotFound` if the object is not found in the results collection. - */ -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns the index of the first object in the results collection matching the predicate. - - @param predicate The predicate with which to filter the objects. - - @return The index of the object, or `NSNotFound` if the object is not found in the results collection. - */ -- (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate; - -/** - Returns all the objects matching the given predicate in the results collection. - - @param predicateFormat A predicate format string, optionally followed by a variable number of arguments. - - @return An `RLMResults` of objects that match the given predicate. - */ -- (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...; - -/// :nodoc: -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - -/** - Returns all the objects matching the given predicate in the results collection. - - @param predicate The predicate with which to filter the objects. - - @return An `RLMResults` of objects that match the given predicate. - */ -- (RLMResults *)objectsWithPredicate:(NSPredicate *)predicate; - -/** - Returns a sorted `RLMResults` from an existing results collection. - - @param property The property name to sort by. - @param ascending The direction to sort in. - - @return An `RLMResults` sorted by the specified property. - */ -- (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL)ascending; - -/** - Returns a sorted `RLMResults` from an existing results collection. - - @param properties An array of `RLMSortDescriptor`s to sort by. - - @return An `RLMResults` sorted by the specified properties. - */ -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; - -#pragma mark - Notifications - -/** - Registers a block to be called each time the results collection changes. - - The block will be asynchronously called with the initial results collection, - and then called again after each write transaction which changes either any - of the objects in the results, or which objects are in the results. - - The `change` parameter will be `nil` the first time the block is called. - For each call after that, it will contain information about - which rows in the results collection were added, removed or modified. If a - write transaction did not modify any objects in the results collection, - the block is not called at all. See the `RLMCollectionChange` documentation for - information on how the changes are reported and an example of updating a - `UITableView`. - - If an error occurs the block will be called with `nil` for the results - parameter and a non-`nil` error. Currently the only errors that can occur are - when opening the Realm on the background worker thread. - - At the time when the block is called, the `RLMResults` object will be fully - evaluated and up-to-date, and as long as you do not perform a write transaction - on the same thread or explicitly call `-[RLMRealm refresh]`, accessing it will - never perform blocking work. - - Notifications are delivered via the standard run loop, and so can't be - delivered while the run loop is blocked by other activity. When - notifications can't be delivered instantly, multiple notifications may be - coalesced into a single notification. This can include the notification - with the initial results. For example, the following code performs a write - transaction immediately after adding the notification block, so there is no - opportunity for the initial notification to be delivered first. As a - result, the initial notification will reflect the state of the Realm after - the write transaction. - - RLMResults *results = [Dog allObjects]; - NSLog(@"dogs.count: %zu", dogs.count); // => 0 - self.token = [results addNotificationBlock:^(RLMResults *dogs, - RLMCollectionChange *changes, - NSError *error) { - // Only fired once for the example - NSLog(@"dogs.count: %zu", dogs.count); // => 1 - }]; - [realm transactionWithBlock:^{ - Dog *dog = [[Dog alloc] init]; - dog.name = @"Rex"; - [realm addObject:dog]; - }]; - // end of run loop execution context - - You must retain the returned token for as long as you want updates to continue - to be sent to the block. To stop receiving updates, call `-stop` on the token. - - @warning This method cannot be called during a write transaction, or when the - containing Realm is read-only. - - @param block The block to be called whenever a change occurs. - @return A token which must be held for as long as you want updates to be delivered. - */ -- (RLMNotificationToken *)addNotificationBlock:(void (^)(RLMResults *__nullable results, - RLMCollectionChange *__nullable change, - NSError *__nullable error))block __attribute__((warn_unused_result)); - -#pragma mark - Aggregating Property Values - -/** - Returns the minimum (lowest) value of the given property among all the objects - represented by the results collection. - - NSNumber *min = [results minOfProperty:@"age"]; - - @warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties. - - @param property The property whose minimum value is desired. Only properties of types `int`, `float`, `double`, and - `NSDate` are supported. - - @return The minimum value of the property. - */ -- (nullable id)minOfProperty:(NSString *)property; - -/** - Returns the maximum (highest) value of the given property among all the objects represented by the results collection. - - NSNumber *max = [results maxOfProperty:@"age"]; - - @warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties. - - @param property The property whose maximum value is desired. Only properties of types `int`, `float`, `double`, and - `NSDate` are supported. - - @return The maximum value of the property. - */ -- (nullable id)maxOfProperty:(NSString *)property; - -/** - Returns the sum of the values of a given property over all the objects represented by the results collection. - - NSNumber *sum = [results sumOfProperty:@"age"]; - - @warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties. - - @param property The property whose values should be summed. Only properties of types `int`, `float`, and `double` are - supported. - - @return The sum of the given property. - */ -- (NSNumber *)sumOfProperty:(NSString *)property; - -/** - Returns the average value of a given property over the objects represented by the results collection. - - NSNumber *average = [results averageOfProperty:@"age"]; - - @warning You cannot use this method on `RLMObject`, `RLMArray`, and `NSData` properties. - - @param property The property whose average value should be calculated. Only properties of types `int`, `float`, and - `double` are supported. - - @return The average value of the given property. This will be of type `double` for both `float` and `double` - properties. - */ -- (nullable NSNumber *)averageOfProperty:(NSString *)property; - -/// :nodoc: -- (RLMObjectType)objectAtIndexedSubscript:(NSUInteger)index; - -#pragma mark - Unavailable Methods - -/** - `-[RLMResults init]` is not available because `RLMResults` cannot be created directly. - `RLMResults` can be obtained by querying a Realm. - */ -- (instancetype)init __attribute__((unavailable("RLMResults cannot be created directly"))); - -/** - `+[RLMResults new]` is not available because `RLMResults` cannot be created directly. - `RLMResults` can be obtained by querying a Realm. - */ -+ (instancetype)new __attribute__((unavailable("RLMResults cannot be created directly"))); - -@end - -/** - `RLMLinkingObjects` is an auto-updating container type. It represents a collection of objects that link to its - parent object. - - For more information, please see the "Inverse Relationships" section in the - [documentation](https://realm.io/docs/objc/latest/#relationships). - */ -@interface RLMLinkingObjects : RLMResults -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMResults_Private.h b/Example/Pods/Realm/include/RLMResults_Private.h deleted file mode 100644 index f74b4fd..0000000 --- a/Example/Pods/Realm/include/RLMResults_Private.h +++ /dev/null @@ -1,32 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -@class RLMObjectSchema; - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMResults () -@property (nonatomic, readonly, getter=isAttached) BOOL attached; - -+ (instancetype)emptyDetachedResults; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSchema.h b/Example/Pods/Realm/include/RLMSchema.h deleted file mode 100644 index 2b11792..0000000 --- a/Example/Pods/Realm/include/RLMSchema.h +++ /dev/null @@ -1,77 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMObjectSchema; - -/** - `RLMSchema` instances represent collections of model object schemas managed by a Realm. - - When using Realm, `RLMSchema` instances allow performing migrations and - introspecting the database's schema. - - Schemas map to collections of tables in the core database. - */ -@interface RLMSchema : NSObject - -#pragma mark - Properties - -/** - An `NSArray` containing `RLMObjectSchema`s for all object types in the Realm. - - This property is intended to be used during migrations for dynamic introspection. - - @see `RLMObjectSchema` - */ -@property (nonatomic, readonly, copy) NSArray *objectSchema; - -#pragma mark - Methods - -/** - Returns an `RLMObjectSchema` for the given class name in the schema. - - @param className The object class name. - @return An `RLMObjectSchema` for the given class in the schema. - - @see `RLMObjectSchema` - */ -- (nullable RLMObjectSchema *)schemaForClassName:(NSString *)className; - -/** - Looks up and returns an `RLMObjectSchema` for the given class name in the Realm. - - If there is no object of type `className` in the schema, an exception will be thrown. - - @param className The object class name. - @return An `RLMObjectSchema` for the given class in this Realm. - - @see `RLMObjectSchema` - */ -- (RLMObjectSchema *)objectForKeyedSubscript:(NSString *)className; - -/** - Returns whether two `RLMSchema` instances are equivalent. - */ -- (BOOL)isEqualToSchema:(RLMSchema *)schema; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSchema_Private.h b/Example/Pods/Realm/include/RLMSchema_Private.h deleted file mode 100644 index f5823d1..0000000 --- a/Example/Pods/Realm/include/RLMSchema_Private.h +++ /dev/null @@ -1,54 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@class RLMRealm; - -// -// RLMSchema private interface -// -@interface RLMSchema () - -/** - Returns an `RLMSchema` containing only the given `RLMObject` subclasses. - - @param classes The classes to be included in the schema. - - @return An `RLMSchema` containing only the given classes. - */ -+ (instancetype)schemaWithObjectClasses:(NSArray *)classes; - -@property (nonatomic, readwrite, copy) NSArray *objectSchema; - -// schema based on runtime objects -+ (instancetype)sharedSchema; - -// schema based upon all currently registered object classes -+ (instancetype)partialSharedSchema; - -// class for string -+ (nullable Class)classForString:(NSString *)className; - -+ (nullable RLMObjectSchema *)sharedSchemaForClass:(Class)cls; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSchema_Private.hpp b/Example/Pods/Realm/include/RLMSchema_Private.hpp deleted file mode 100644 index 197ddee..0000000 --- a/Example/Pods/Realm/include/RLMSchema_Private.hpp +++ /dev/null @@ -1,31 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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 "RLMSchema_Private.h" - -#import - -namespace realm { - class Schema; - class ObjectSchema; -} - -@interface RLMSchema () -+ (instancetype)dynamicSchemaFromObjectStoreSchema:(realm::Schema const&)objectStoreSchema; -- (realm::Schema)objectStoreCopy; -@end diff --git a/Example/Pods/Realm/include/RLMSwiftBridgingHeader.h b/Example/Pods/Realm/include/RLMSwiftBridgingHeader.h deleted file mode 100644 index 4758043..0000000 --- a/Example/Pods/Realm/include/RLMSwiftBridgingHeader.h +++ /dev/null @@ -1,49 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import - -@interface RLMRealm (Swift) -+ (void)resetRealmState; -@end - -@interface RLMArray (Swift) - -- (instancetype)initWithObjectClassName:(NSString *)objectClassName; - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args; -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - -@end - -@interface RLMResults (Swift) - -- (NSUInteger)indexOfObjectWhere:(NSString *)predicateFormat args:(va_list)args; -- (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; - -@end - -@interface RLMObjectBase (Swift) - -- (instancetype)initWithRealm:(RLMRealm *)realm schema:(RLMObjectSchema *)schema defaultValues:(BOOL)useDefaults; - -+ (RLMResults *)objectsWhere:(NSString *)predicateFormat args:(va_list)args; -+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args; - -@end diff --git a/Example/Pods/Realm/include/RLMSwiftSupport.h b/Example/Pods/Realm/include/RLMSwiftSupport.h deleted file mode 100644 index 6e45b65..0000000 --- a/Example/Pods/Realm/include/RLMSwiftSupport.h +++ /dev/null @@ -1,30 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSwiftSupport : NSObject - -+ (BOOL)isSwiftClassName:(NSString *)className; -+ (NSString *)demangleClassName:(NSString *)className; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncConfiguration.h b/Example/Pods/Realm/include/RLMSyncConfiguration.h deleted file mode 100644 index 6181d91..0000000 --- a/Example/Pods/Realm/include/RLMSyncConfiguration.h +++ /dev/null @@ -1,60 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -@class RLMSyncUser; - -NS_ASSUME_NONNULL_BEGIN - -/** - A configuration object representing configuration state for a Realm which is intended to sync with a Realm Object - Server. - */ -@interface RLMSyncConfiguration : NSObject - -/// The user to which the remote Realm belongs. -@property (nonatomic, readonly) RLMSyncUser *user; - -/** - The URL of the remote Realm upon the Realm Object Server. - - @warning The URL cannot end with `.realm`, `.realm.lock` or `.realm.management`. - */ -@property (nonatomic, readonly) NSURL *realmURL; - -/** - Create a sync configuration instance. - - @param user A `RLMSyncUser` that owns the Realm at the given URL. - @param url The unresolved absolute URL to the Realm on the Realm Object Server, e.g. - `realm://example.org/~/path/to/realm`. "Unresolved" means the path should - contain the wildcard marker `~`, which will automatically be filled in with - the user identity by the Realm Object Server. - */ -- (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url; - -/// :nodoc: -- (instancetype)init __attribute__((unavailable("This type cannot be created directly"))); - -/// :nodoc: -+ (instancetype)new __attribute__((unavailable("This type cannot be created directly"))); - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncConfiguration_Private.h b/Example/Pods/Realm/include/RLMSyncConfiguration_Private.h deleted file mode 100644 index 1001ae8..0000000 --- a/Example/Pods/Realm/include/RLMSyncConfiguration_Private.h +++ /dev/null @@ -1,38 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSUInteger, RLMSyncStopPolicy) { - RLMSyncStopPolicyImmediately, - RLMSyncStopPolicyLiveIndefinitely, - RLMSyncStopPolicyAfterChangesUploaded, -}; - -@interface RLMSyncConfiguration () - -@property (nonatomic, readwrite) RLMSyncStopPolicy stopPolicy; - -// Internal-only APIs -@property (nullable, nonatomic) NSURL *customFileURL; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncConfiguration_Private.hpp b/Example/Pods/Realm/include/RLMSyncConfiguration_Private.hpp deleted file mode 100644 index 1a80e7f..0000000 --- a/Example/Pods/Realm/include/RLMSyncConfiguration_Private.hpp +++ /dev/null @@ -1,31 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncConfiguration_Private.h" - -namespace realm { -struct SyncConfig; -} - -@interface RLMSyncConfiguration () - -- (instancetype)initWithRawConfig:(realm::SyncConfig)config; - -- (realm::SyncConfig)rawConfiguration; - -@end diff --git a/Example/Pods/Realm/include/RLMSyncCredentials.h b/Example/Pods/Realm/include/RLMSyncCredentials.h deleted file mode 100644 index bb19fbe..0000000 --- a/Example/Pods/Realm/include/RLMSyncCredentials.h +++ /dev/null @@ -1,106 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil.h" - -NS_ASSUME_NONNULL_BEGIN - -/// A token representing an identity provider's credentials. -typedef NSString *RLMSyncCredentialsToken; - -/// A type representing the unique identifier of a Realm Object Server identity provider. -typedef NSString *RLMIdentityProvider RLM_EXTENSIBLE_STRING_ENUM; - -/// The debug identity provider, which accepts any token string and creates a user associated with that token if one -/// does not yet exist. Not enabled for Realm Object Server configured for production. -extern RLMIdentityProvider const RLMIdentityProviderDebug; - -/// The username/password identity provider. User accounts are handled by the Realm Object Server directly without the -/// involvement of a third-party identity provider. -extern RLMIdentityProvider const RLMIdentityProviderUsernamePassword; - -/// A Facebook account as an identity provider. -extern RLMIdentityProvider const RLMIdentityProviderFacebook; - -/// A Google account as an identity provider. -extern RLMIdentityProvider const RLMIdentityProviderGoogle; - -/// A CloudKit account as an identity provider. -extern RLMIdentityProvider const RLMIdentityProviderCloudKit; - -/** - Opaque credentials representing a specific Realm Object Server user. - */ -@interface RLMSyncCredentials : NSObject - -/// An opaque credentials token containing information that uniquely identifies a Realm Object Server user. -@property (nonatomic, readonly) RLMSyncCredentialsToken token; - -/// The name of the identity provider which generated the credentials token. -@property (nonatomic, readonly) RLMIdentityProvider provider; - -/// A dictionary containing additional pertinent information. In most cases this is automatically configured. -@property (nonatomic, readonly) NSDictionary *userInfo; - -/** - Construct and return credentials from a Facebook account token. - */ -+ (instancetype)credentialsWithFacebookToken:(RLMSyncCredentialsToken)token; - -/** - Construct and return credentials from a Google account token. - */ -+ (instancetype)credentialsWithGoogleToken:(RLMSyncCredentialsToken)token; - -/** - Construct and return credentials from an CloudKit account token. - */ -+ (instancetype)credentialsWithCloudKitToken:(RLMSyncCredentialsToken)token; - -/** - Construct and return credentials from a Realm Object Server username and password. - */ -+ (instancetype)credentialsWithUsername:(NSString *)username - password:(NSString *)password - register:(BOOL)shouldRegister; - -/** - Construct and return special credentials representing a token that can be directly used to open a Realm. The identity - is used to uniquely identify the user across application launches. - */ -+ (instancetype)credentialsWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity; - -/** - Construct and return credentials with a custom token string, identity provider string, and optional user info. In most - cases, the convenience initializers should be used instead. - */ -- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token - provider:(RLMIdentityProvider)provider - userInfo:(nullable NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER; - -/// :nodoc: -- (instancetype)init __attribute__((unavailable("RLMSyncCredentials cannot be created directly"))); - -/// :nodoc: -+ (instancetype)new __attribute__((unavailable("RLMSyncCredentials cannot be created directly"))); - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMSyncErrorResponseModel.h b/Example/Pods/Realm/include/RLMSyncErrorResponseModel.h deleted file mode 100644 index 930a7ea..0000000 --- a/Example/Pods/Realm/include/RLMSyncErrorResponseModel.h +++ /dev/null @@ -1,36 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 -#import "RLMSyncUtil_Private.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncErrorResponseModel : NSObject RLM_SYNC_UNINITIALIZABLE - -@property (nonatomic, readonly, assign) NSInteger status; -@property (nonatomic, readonly, assign) NSInteger code; -@property (nonatomic, readonly, copy) NSString *title; -@property (nonatomic, readonly, copy) NSString *hint; - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncManager.h b/Example/Pods/Realm/include/RLMSyncManager.h deleted file mode 100644 index e2f559f..0000000 --- a/Example/Pods/Realm/include/RLMSyncManager.h +++ /dev/null @@ -1,102 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil.h" - -@class RLMSyncSession; - -/// An enum representing different levels of sync-related logging that can be configured. -typedef NS_ENUM(NSUInteger, RLMSyncLogLevel) { - /// Nothing will ever be logged. - RLMSyncLogLevelOff, - /// Only fatal errors will be logged. - RLMSyncLogLevelFatal, - /// Only errors will be logged. - RLMSyncLogLevelError, - /// Warnings and errors will be logged. - RLMSyncLogLevelWarn, - /// Information about sync events will be logged. Fewer events will be logged in order to avoid overhead. - RLMSyncLogLevelInfo, - /// Information about sync events will be logged. More events will be logged than with `RLMSyncLogLevelInfo`. - RLMSyncLogLevelDetail, - /// Log information that can aid in debugging. - /// - /// - warning: Will incur a measurable performance impact. - RLMSyncLogLevelDebug, - /// Log information that can aid in debugging. More events will be logged than with `RLMSyncLogLevelDebug`. - /// - /// - warning: Will incur a measurable performance impact. - RLMSyncLogLevelTrace, - /// Log information that can aid in debugging. More events will be logged than with `RLMSyncLogLevelTrace`. - /// - /// - warning: Will incur a measurable performance impact. - RLMSyncLogLevelAll -}; - -NS_ASSUME_NONNULL_BEGIN - -/// A block type representing a block which can be used to report a sync-related error to the application. If the error -/// pertains to a specific session, that session will also be passed into the block. -typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable); - -/** - A singleton manager which serves as a central point for sync-related configuration. - */ -@interface RLMSyncManager : NSObject - -/** - An optional block which can be used to report sync-related errors to your application. Errors reported through this - mechanism are always fatal; they represent attempts to open sessions which are invalid (for example, using malformed - URLs). - */ -@property (nullable, nonatomic, copy) RLMSyncErrorReportingBlock errorHandler; - -/** - A reverse-DNS string uniquely identifying this application. In most cases this is automatically set by the SDK, and - does not have to be explicitly configured. - */ -@property (nonatomic, copy) NSString *appID; - -/** - Whether SSL certificate validation should be disabled. SSL certificate validation is ON by default. Setting this - property after at least one synced Realm or standalone Session has been opened is a no-op. - - @warning NEVER disable certificate validation for clients and servers in production. - */ -@property (nonatomic) BOOL disableSSLValidation; - -/** - The logging threshold which newly opened synced Realms will use. Defaults to `RLMSyncLogLevelInfo`. Set this before - any synced Realms are opened. Logging strings are output to ASL. - */ -@property (nonatomic) RLMSyncLogLevel logLevel; - -/// The sole instance of the singleton. -+ (instancetype)sharedManager NS_REFINED_FOR_SWIFT; - -/// :nodoc: -- (instancetype)init __attribute__((unavailable("RLMSyncManager cannot be created directly"))); - -/// :nodoc: -+ (instancetype)new __attribute__((unavailable("RLMSyncManager cannot be created directly"))); - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMSyncManager_Private.h b/Example/Pods/Realm/include/RLMSyncManager_Private.h deleted file mode 100644 index b704dab..0000000 --- a/Example/Pods/Realm/include/RLMSyncManager_Private.h +++ /dev/null @@ -1,54 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncManager.h" - -#import "RLMSyncUtil_Private.h" - -typedef NS_ENUM(NSUInteger, RLMSyncSessionErrorKind) { - RLMSyncSessionErrorKindDebug, - RLMSyncSessionErrorKindSessionFatal, - RLMSyncSessionErrorKindAccessDenied, - RLMSyncSessionErrorKindUserFatal, -}; - -@class RLMSyncUser, RLMSyncConfiguration; - -// All private API methods are threadsafe and synchronized, unless denoted otherwise. Since they are expected to be -// called very infrequently, this should pose no issues. - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncManager () - -@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock sessionCompletionNotifier; - -- (void)_fireError:(NSError *)error; - -- (void)_fireErrorWithCode:(int)errorCode - message:(NSString *)message - session:(RLMSyncSession *)session - errorClass:(RLMSyncSessionErrorKind)errorClass; - -- (NSArray *)_allUsers; - -+ (void)resetForTesting; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMSyncPermissionChange.h b/Example/Pods/Realm/include/RLMSyncPermissionChange.h deleted file mode 100644 index 9581afe..0000000 --- a/Example/Pods/Realm/include/RLMSyncPermissionChange.h +++ /dev/null @@ -1,107 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class RLMSyncUser; - -/// An enum representing the different states a sync management object can take. -typedef NS_ENUM(NSUInteger, RLMSyncManagementObjectStatus) { - /// The management object has not yet been processed by the object server. - RLMSyncManagementObjectStatusNotProcessed, - /// The operations encoded in the management object have been successfully - /// performed by the object server. - RLMSyncManagementObjectStatusSuccess, - /** - The operations encoded in the management object were not successfully - performed by the object server. - - Refer to the `statusCode` and `statusMessage` properties for more details - about the error. - */ - RLMSyncManagementObjectStatusError, -}; - -/** - This model is used for requesting changes to a Realm's permissions. - - It should be used in conjunction with an `RLMSyncUser`'s management Realm. - - See https://realm.io/docs/realm-object-server/#permissions for general - documentation. - */ -@interface RLMSyncPermissionChange : RLMObject - -/// The globally unique ID string of this permission change object. -@property (readonly) NSString *id; - -/// The date this object was initially created. -@property (readonly) NSDate *createdAt; - -/// The date this object was last modified. -@property (readonly) NSDate *updatedAt; - -/// The status code of the object that was processed by Realm Object Server. -@property (nullable, readonly) NSNumber *statusCode; - -/// An error or informational message, typically written to by the Realm Object Server. -@property (nullable, readonly) NSString *statusMessage; - -/// Sync management object status. -@property (readonly) RLMSyncManagementObjectStatus status; - -/// The remote URL to the realm. -@property (readonly) NSString *realmUrl; - -/// The identity of a user affected by this permission change. -@property (readonly) NSString *userId; - -/// Define read access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. -@property (nullable, readonly) NSNumber *mayRead; -/// Define write access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. -@property (nullable, readonly) NSNumber *mayWrite; -/// Define management access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. -@property (nullable, readonly) NSNumber *mayManage; - -/** - Construct a permission change object used to change the access permissions for a user on a Realm. - - @param realmURL The Realm URL whose permissions settings should be changed. - Use `*` to change the permissions of all Realms managed by the management Realm's `RLMSyncUser`. - @param userID The user or users who should be granted these permission changes. - Use `*` to change the permissions for all users. - @param mayRead Define read access. Set to `YES` or `NO` to update this value. - Leave unset to preserve the existing setting. - @param mayWrite Define write access. Set to `YES` or `NO` to update this value. - Leave unset to preserve the existing setting. - @param mayManage Define management access. Set to `YES` or `NO` to update this value. - Leave unset to preserve the existing setting. - */ -+ (instancetype)permissionChangeWithRealmURL:(NSString *)realmURL - userID:(NSString *)userID - read:(nullable NSNumber *)mayRead - write:(nullable NSNumber *)mayWrite - manage:(nullable NSNumber *)mayManage; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncPermissionChange_Private.h b/Example/Pods/Realm/include/RLMSyncPermissionChange_Private.h deleted file mode 100644 index df632bc..0000000 --- a/Example/Pods/Realm/include/RLMSyncPermissionChange_Private.h +++ /dev/null @@ -1,39 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncPermissionChange.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncPermissionChange() - -@property (readwrite) NSString *id; -@property (readwrite) NSDate *createdAt; -@property (readwrite) NSDate *updatedAt; -@property (nullable, readwrite) NSNumber *statusCode; -@property (nullable, readwrite) NSString *statusMessage; -@property (readwrite) NSString *realmUrl; -@property (readwrite) NSString *userId; - -@property (nullable, readwrite) NSNumber *mayRead; -@property (nullable, readwrite) NSNumber *mayWrite; -@property (nullable, readwrite) NSNumber *mayManage; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncSession.h b/Example/Pods/Realm/include/RLMSyncSession.h deleted file mode 100644 index 46c11e3..0000000 --- a/Example/Pods/Realm/include/RLMSyncSession.h +++ /dev/null @@ -1,61 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -/** - The current state of a sync session object. - */ -typedef NS_ENUM(NSUInteger, RLMSyncSessionState) { - /// The sync session is bound to the Realm Object Server and communicating with it. - RLMSyncSessionStateActive, - /// The sync session is not currently communicating with the Realm Object Server. - RLMSyncSessionStateInactive, - /// The sync session encountered an error and is invalid; it should be discarded. - RLMSyncSessionStateInvalid -}; - -@class RLMSyncUser, RLMSyncConfiguration; - -NS_ASSUME_NONNULL_BEGIN - -/** - An object encapsulating a Realm Object Server "session". Sessions represent the communication between the client (and a - local Realm file on disk), and the server (and a remote Realm at a given URL stored on a Realm Object Server). - - Sessions are always created by the SDK and vended out through various APIs. The lifespans of sessions associated with - Realms are managed automatically. - */ -@interface RLMSyncSession : NSObject - -/// The session's current state. -@property (nonatomic, readonly) RLMSyncSessionState state; - -/// The Realm Object Server URL of the remote Realm this session corresponds to. -@property (nullable, nonatomic, readonly) NSURL *realmURL; - -/// The user that owns this session. -- (nullable RLMSyncUser *)parentUser; - -/// If the session is valid, return a sync configuration that can be used to open the Realm associated with this -/// session. -- (nullable RLMSyncConfiguration *)configuration; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp b/Example/Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp deleted file mode 100644 index 30be435..0000000 --- a/Example/Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp +++ /dev/null @@ -1,40 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import - -namespace realm { -class SyncSession; -} - -@class RLMSyncUser; - -/// An object that handles refreshing a session's auth token periodically, as long as that session remains viable. -/// Intended for easy removal once the new auth system is in place. -@interface RLMSyncSessionRefreshHandle : NSObject - -- (instancetype)initWithFullURLPath:(NSString *)urlPath - user:(RLMSyncUser *)user - session:(std::shared_ptr)session; - -- (void)scheduleRefreshTimer:(NSTimeInterval)fireTime; -- (void)invalidate; - -@end diff --git a/Example/Pods/Realm/include/RLMSyncSession_Private.hpp b/Example/Pods/Realm/include/RLMSyncSession_Private.hpp deleted file mode 100644 index 084c7dc..0000000 --- a/Example/Pods/Realm/include/RLMSyncSession_Private.hpp +++ /dev/null @@ -1,42 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncSession.h" - -#import "RLMSyncUtil_Private.h" -#import - -namespace realm { -class SyncSession; -} - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncSession () RLM_SYNC_UNINITIALIZABLE - -- (instancetype)initWithSyncSession:(std::shared_ptr)session; - -/// Wait for pending uploads to complete or the session to expire, and dispatch the callback onto the specified queue. -- (BOOL)waitForUploadCompletionOnQueue:(nullable dispatch_queue_t)queue callback:(void(^)(void))callback; - -/// Wait for pending downloads to complete or the session to expire, and dispatch the callback onto the specified queue. -- (BOOL)waitForDownloadCompletionOnQueue:(nullable dispatch_queue_t)queue callback:(void(^)(void))callback; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncUser.h b/Example/Pods/Realm/include/RLMSyncUser.h deleted file mode 100644 index a14c043..0000000 --- a/Example/Pods/Realm/include/RLMSyncUser.h +++ /dev/null @@ -1,131 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -@class RLMSyncUser, RLMSyncCredentials, RLMSyncSession, RLMRealm; - -/** - The state of the user object. - */ -typedef NS_ENUM(NSUInteger, RLMSyncUserState) { - /// The user is logged out. Call `logInWithCredentials:...` with valid credentials to log the user back in. - RLMSyncUserStateLoggedOut, - /// The user is logged in, and any Realms associated with it are syncing with the Realm Object Server. - RLMSyncUserStateActive, - /// The user has encountered a fatal error state, and cannot be used. - RLMSyncUserStateError, -}; - -/// A block type used for APIs which asynchronously vend a `RLMSyncUser`. -typedef void(^RLMUserCompletionBlock)(RLMSyncUser * _Nullable, NSError * _Nullable); - -NS_ASSUME_NONNULL_BEGIN - -/** - A `RLMSyncUser` instance represents a single Realm Object Server user account (or just user). - - A user may have one or more credentials associated with it. These credentials uniquely identify the user to a - third-party auth provider, and are used to sign into a Realm Object Server user account. - - Note that users are only vended out via SDK APIs, and only one user instance ever exists for a given user account. - */ -@interface RLMSyncUser : NSObject - -/** - A dictionary of all valid, logged-in user identities corresponding to their `RLMSyncUser` objects. - */ -+ (NSDictionary *)allUsers NS_REFINED_FOR_SWIFT; - -/** - The logged-in user. `nil` if none exists. - - @warning Throws an exception if more than one logged-in user exists. - */ -+ (nullable RLMSyncUser *)currentUser NS_REFINED_FOR_SWIFT; - -/** - The unique Realm Object Server user ID string identifying this user. - */ -@property (nullable, nonatomic, readonly) NSString *identity; - -/** - The URL of the authentication server this user will communicate with. - */ -@property (nullable, nonatomic, readonly) NSURL *authenticationServer; - -/** - The current state of the user. - */ -@property (nonatomic, readonly) RLMSyncUserState state; - -/** - Create, log in, and asynchronously return a new user object, specifying a custom timeout for the network request. - Credentials identifying the user must be passed in. The user becomes available in the completion block, at which point - it is ready for use. - */ -+ (void)logInWithCredentials:(RLMSyncCredentials *)credentials - authServerURL:(NSURL *)authServerURL - timeout:(NSTimeInterval)timeout - onCompletion:(RLMUserCompletionBlock)completion NS_REFINED_FOR_SWIFT; - -/** - Create, log in, and asynchronously return a new user object. Credentials identifying the user must be passed in. The - user becomes available in the completion block, at which point it is ready for use. - */ -+ (void)logInWithCredentials:(RLMSyncCredentials *)credentials - authServerURL:(NSURL *)authServerURL - onCompletion:(RLMUserCompletionBlock)completion -NS_SWIFT_UNAVAILABLE("Use the full version of this API."); - -/** - Log a user out, destroying their server state, deregistering them from the SDK, and removing any synced Realms - associated with them from on-disk storage. If the user is already logged out or in an error state, this is a no-op. - - This method should be called whenever the application is committed to not using a user again unless they are recreated. - Failing to call this method may result in unused files and metadata needlessly taking up space. - */ -- (void)logOut; - -/** - Retrieve a valid session object belonging to this user for a given URL, or `nil` if no such object exists. - */ -- (nullable RLMSyncSession *)sessionForURL:(NSURL *)url; - -/** - Retrieve all the valid sessions belonging to this user. - */ -- (NSArray *)allSessions; - -/** - Returns an instance of the Management Realm owned by the user. - - This Realm can be used to control access permissions for Realms managed by the user. - This includes granting other users access to Realms. - */ -- (RLMRealm *)managementRealmWithError:(NSError **)error NS_REFINED_FOR_SWIFT; - -/// :nodoc: -- (instancetype)init __attribute__((unavailable("RLMSyncUser cannot be created directly"))); - -/// :nodoc: -+ (instancetype)new __attribute__((unavailable("RLMSyncUser cannot be created directly"))); - -NS_ASSUME_NONNULL_END - -@end diff --git a/Example/Pods/Realm/include/RLMSyncUser_Private.hpp b/Example/Pods/Realm/include/RLMSyncUser_Private.hpp deleted file mode 100644 index 20d9f6d..0000000 --- a/Example/Pods/Realm/include/RLMSyncUser_Private.hpp +++ /dev/null @@ -1,51 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncUser.h" - -#import "RLMSyncConfiguration.h" -#import "RLMSyncUtil_Private.h" - -#include "sync/sync_config.hpp" -#include "sync/impl/sync_metadata.hpp" - -@class RLMSyncConfiguration; - -using namespace realm; - -typedef void(^RLMFetchedRealmCompletionBlock)(NSError * _Nullable, RLMRealm * _Nullable, BOOL * _Nonnull); - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncUser () - -- (void)_bindSessionWithPath:(const std::string&)path - config:(const SyncConfig&)config - session:(std::shared_ptr)session - completion:(nullable RLMSyncBasicErrorReportingBlock)completion - isStandalone:(BOOL)standalone; - -- (instancetype)initWithSyncUser:(std::shared_ptr)user; -- (std::shared_ptr)_syncUser; -- (nullable NSString *)_refreshToken; - -- (void)_unregisterRefreshHandleForURLPath:(NSString *)path; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncUtil.h b/Example/Pods/Realm/include/RLMSyncUtil.h deleted file mode 100644 index 2cc4ab6..0000000 --- a/Example/Pods/Realm/include/RLMSyncUtil.h +++ /dev/null @@ -1,64 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -/// A token originating from the Realm Object Server. -typedef NSString* RLMServerToken; - -NS_ASSUME_NONNULL_BEGIN - -/// The error domain string for all SDK errors related to synchronization functionality. -extern NSString *const RLMSyncErrorDomain; - -/// An error which is related to authentication to a Realm Object Server. -typedef RLM_ERROR_ENUM(NSInteger, RLMSyncAuthError, RLMSyncErrorDomain) { - /// An error that indicates that the provided credentials are invalid. - RLMSyncAuthErrorInvalidCredential = 611, - - /// An error that indicates that the user with provided credentials does not exist. - RLMSyncAuthErrorUserDoesNotExist = 612, - - /// An error that indicates that the user cannot be registered as it exists already. - RLMSyncAuthErrorUserAlreadyExists = 613, -}; - -/// An error which is related to synchronization with a Realm Object Server. -typedef RLM_ERROR_ENUM(NSInteger, RLMSyncError, RLMSyncErrorDomain) { - /// An error that indicates that the response received from the authentication server was malformed. - RLMSyncErrorBadResponse = 1, - - /// An error that indicates that the supplied Realm path was invalid, or could not be resolved by the authentication - /// server. - RLMSyncErrorBadRemoteRealmPath = 2, - - /// An error that indicates that the response received from the authentication server was an HTTP error code. The - /// `userInfo` dictionary contains the actual error code value. - RLMSyncErrorHTTPStatusCodeError = 3, - - /// An error that indicates a problem with the session (a specific Realm opened for sync). - RLMSyncErrorClientSessionError = 4, - - /// An error that indicates a problem with a specific user. - RLMSyncErrorClientUserError = 5, - - /// An error that indicates an internal error with the underlying synchronization engine. Only for information. - RLMSyncErrorClientInternalError = 6, -}; - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMSyncUtil_Private.h b/Example/Pods/Realm/include/RLMSyncUtil_Private.h deleted file mode 100644 index d60da5d..0000000 --- a/Example/Pods/Realm/include/RLMSyncUtil_Private.h +++ /dev/null @@ -1,97 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import -#import - -@class RLMSyncUser; - -typedef void(^RLMSyncCompletionBlock)(NSError * _Nullable, NSDictionary * _Nullable); -typedef void(^RLMSyncBasicErrorReportingBlock)(NSError * _Nullable); - -typedef NSString* RLMServerPath; - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMRealmConfiguration (RealmSync) -+ (instancetype)managementConfigurationForUser:(RLMSyncUser *)user; -@end - -extern RLMIdentityProvider const RLMIdentityProviderAccessToken; -extern RLMIdentityProvider const RLMIdentityProviderRealm; - -extern NSString *const kRLMSyncAppIDKey; -extern NSString *const kRLMSyncDataKey; -extern NSString *const kRLMSyncErrorJSONKey; -extern NSString *const kRLMSyncErrorStatusCodeKey; -extern NSString *const kRLMSyncIdentityKey; -extern NSString *const kRLMSyncPasswordKey; -extern NSString *const kRLMSyncPathKey; -extern NSString *const kRLMSyncProviderKey; -extern NSString *const kRLMSyncRegisterKey; -extern NSString *const kRLMSyncUnderlyingErrorKey; - -#define RLM_SYNC_UNINITIALIZABLE \ -- (instancetype)init __attribute__((unavailable("This type cannot be created directly"))); \ -+ (instancetype)new __attribute__((unavailable("This type cannot be created directly"))); - -NS_ASSUME_NONNULL_END - -/// A macro to parse a string out of a JSON dictionary, or return nil. -#define RLM_SYNC_PARSE_STRING_OR_ABORT(json_macro_val, key_macro_val, prop_macro_val) \ -{ \ -id data = json_macro_val[key_macro_val]; \ -if (![data isKindOfClass:[NSString class]]) { return nil; } \ -self.prop_macro_val = data; \ -} \ - -#define RLM_SYNC_PARSE_OPTIONAL_STRING(json_macro_val, key_macro_val, prop_macro_val) \ -{ \ -id data = json_macro_val[key_macro_val]; \ -if (![data isKindOfClass:[NSString class]]) { data = nil; } \ -self.prop_macro_val = data; \ -} \ - -/// A macro to parse a double out of a JSON dictionary, or return nil. -#define RLM_SYNC_PARSE_DOUBLE_OR_ABORT(json_macro_val, key_macro_val, prop_macro_val) \ -{ \ -id data = json_macro_val[key_macro_val]; \ -if (![data isKindOfClass:[NSNumber class]]) { return nil; } \ -self.prop_macro_val = [data doubleValue]; \ -} \ - -/// A macro to build a sub-model out of a JSON dictionary, or return nil. -#define RLM_SYNC_PARSE_MODEL_OR_ABORT(json_macro_val, key_macro_val, class_macro_val, prop_macro_val) \ -{ \ -id raw = json_macro_val[key_macro_val]; \ -if (![raw isKindOfClass:[NSDictionary class]]) { return nil; } \ -id model = [[class_macro_val alloc] initWithDictionary:raw]; \ -if (!model) { return nil; } \ -self.prop_macro_val = model; \ -} \ - -#define RLM_SYNC_PARSE_OPTIONAL_MODEL(json_macro_val, key_macro_val, class_macro_val, prop_macro_val) \ -{ \ -id model; \ -id raw = json_macro_val[key_macro_val]; \ -if (![raw isKindOfClass:[NSDictionary class]]) { model = nil; } \ -else { model = [[class_macro_val alloc] initWithDictionary:raw]; } \ -self.prop_macro_val = model; \ -} \ diff --git a/Example/Pods/Realm/include/RLMSyncUtil_Private.hpp b/Example/Pods/Realm/include/RLMSyncUtil_Private.hpp deleted file mode 100644 index 279207a..0000000 --- a/Example/Pods/Realm/include/RLMSyncUtil_Private.hpp +++ /dev/null @@ -1,30 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 "RLMSyncUtil_Private.h" - -#import "RLMSyncConfiguration_Private.h" - -#import "sync/sync_manager.hpp" - -namespace realm { - -SyncSessionStopPolicy translateStopPolicy(RLMSyncStopPolicy stopPolicy); -RLMSyncStopPolicy translateStopPolicy(SyncSessionStopPolicy stop_policy); - -} diff --git a/Example/Pods/Realm/include/RLMTokenModels.h b/Example/Pods/Realm/include/RLMTokenModels.h deleted file mode 100644 index bd97092..0000000 --- a/Example/Pods/Realm/include/RLMTokenModels.h +++ /dev/null @@ -1,49 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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 - -#import "RLMSyncUtil_Private.h" - -NS_ASSUME_NONNULL_BEGIN - -@class RLMTokenDataModel; - -@interface RLMTokenModel : NSObject RLM_SYNC_UNINITIALIZABLE - -@property (nonatomic, readonly) NSString *token; -@property (nonatomic, nullable, readonly) NSString *path; -@property (nonatomic, readonly) RLMTokenDataModel *tokenData; - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary; - -@end - -@interface RLMTokenDataModel : NSObject RLM_SYNC_UNINITIALIZABLE - -@property (nonatomic, readonly) NSString *identity; -@property (nonatomic, nullable, readonly) NSString *appID; -@property (nonatomic, nullable, readonly) NSString *path; -@property (nonatomic, readonly) NSTimeInterval expires; -//@property (nonatomic, readonly) NSArray *access; - -- (instancetype)initWithDictionary:(NSDictionary *)jsonDictionary; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/Pods/Realm/include/RLMUpdateChecker.hpp b/Example/Pods/Realm/include/RLMUpdateChecker.hpp deleted file mode 100644 index 7f01ac7..0000000 --- a/Example/Pods/Realm/include/RLMUpdateChecker.hpp +++ /dev/null @@ -1,20 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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. -// -//////////////////////////////////////////////////////////////////////////// - -// Asynchronously check for updates to Realm if running on a simulator -void RLMCheckForUpdates(); diff --git a/Example/Pods/Realm/include/RLMUtil.hpp b/Example/Pods/Realm/include/RLMUtil.hpp deleted file mode 100644 index e0161b9..0000000 --- a/Example/Pods/Realm/include/RLMUtil.hpp +++ /dev/null @@ -1,204 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 -#import -#import - -#import -#import -#import -#import -#import - -namespace realm { - class Mixed; -} - -@class RLMObjectSchema; -@class RLMProperty; - -namespace realm { - class RealmFileException; -} - -__attribute__((format(NSString, 1, 2))) -NSException *RLMException(NSString *fmt, ...); -NSException *RLMException(std::exception const& exception); - -NSError *RLMMakeError(RLMError code, std::exception const& exception); -NSError *RLMMakeError(RLMError code, const realm::util::File::AccessError&); -NSError *RLMMakeError(RLMError code, const realm::RealmFileException&); -NSError *RLMMakeError(std::system_error const& exception); -NSError *RLMMakeError(NSException *exception); - -void RLMSetErrorOrThrow(NSError *error, NSError **outError); - -// returns if the object can be inserted as the given type -BOOL RLMIsObjectValidForProperty(id obj, RLMProperty *prop); - -// gets default values for the given schema (+defaultPropertyValues) -// merges with native property defaults if Swift class -NSDictionary *RLMDefaultValuesForObjectSchema(RLMObjectSchema *objectSchema); - -BOOL RLMIsDebuggerAttached(); -BOOL RLMIsRunningInPlayground(); - -// C version of isKindOfClass -static inline BOOL RLMIsKindOfClass(Class class1, Class class2) { - while (class1) { - if (class1 == class2) return YES; - class1 = class_getSuperclass(class1); - } - return NO; -} - -// Returns whether the class is a descendent of RLMObjectBase -BOOL RLMIsObjectOrSubclass(Class klass); - -// Returns whether the class is an indirect descendant of RLMObjectBase -BOOL RLMIsObjectSubclass(Class klass); - -template -static inline T *RLMDynamicCast(__unsafe_unretained id obj) { - if ([obj isKindOfClass:[T class]]) { - return obj; - } - return nil; -} - -template -static inline T RLMCoerceToNil(__unsafe_unretained T obj) { - if (static_cast(obj) == NSNull.null) { - return nil; - } - else if (__unsafe_unretained auto optional = RLMDynamicCast(obj)) { - return RLMCoerceToNil(optional.underlyingValue); - } - return obj; -} - -// Translate an rlmtype to a string representation -static inline NSString *RLMTypeToString(RLMPropertyType type) { - switch (type) { - case RLMPropertyTypeString: - return @"string"; - case RLMPropertyTypeInt: - return @"int"; - case RLMPropertyTypeBool: - return @"bool"; - case RLMPropertyTypeDate: - return @"date"; - case RLMPropertyTypeData: - return @"data"; - case RLMPropertyTypeDouble: - return @"double"; - case RLMPropertyTypeFloat: - return @"float"; - case RLMPropertyTypeAny: - return @"any"; - case RLMPropertyTypeObject: - return @"object"; - case RLMPropertyTypeArray: - return @"array"; - case RLMPropertyTypeLinkingObjects: - return @"linking objects"; - } - return @"Unknown"; -} - -// String conversion utilities -static inline NSString * RLMStringDataToNSString(realm::StringData stringData) { - static_assert(sizeof(NSUInteger) >= sizeof(size_t), - "Need runtime overflow check for size_t to NSUInteger conversion"); - if (stringData.is_null()) { - return nil; - } - else { - return [[NSString alloc] initWithBytes:stringData.data() - length:stringData.size() - encoding:NSUTF8StringEncoding]; - } -} - -static inline realm::StringData RLMStringDataWithNSString(__unsafe_unretained NSString *const string) { - static_assert(sizeof(size_t) >= sizeof(NSUInteger), - "Need runtime overflow check for NSUInteger to size_t conversion"); - return realm::StringData(string.UTF8String, - [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); -} - -// Binary conversion utilities -static inline NSData *RLMBinaryDataToNSData(realm::BinaryData binaryData) { - return binaryData ? [NSData dataWithBytes:binaryData.data() length:binaryData.size()] : nil; -} - -static inline realm::BinaryData RLMBinaryDataForNSData(__unsafe_unretained NSData *const data) { - // this is necessary to ensure that the empty NSData isn't treated by core as the null realm::BinaryData - // because data.bytes == 0 when data.length == 0 - // the casting bit ensures that we create a data with a non-null pointer - auto bytes = static_cast(data.bytes) ?: static_cast((__bridge void *)data); - return realm::BinaryData(bytes, data.length); -} - -// Date conversion utilities -// These use the reference date and shift the seconds rather than just getting -// the time interval since the epoch directly to avoid losing sub-second precision -static inline NSDate *RLMTimestampToNSDate(realm::Timestamp ts) NS_RETURNS_RETAINED { - if (ts.is_null()) - return nil; - auto timeInterval = ts.get_seconds() - NSTimeIntervalSince1970 + ts.get_nanoseconds() / 1'000'000'000.0; - return [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:timeInterval]; -} - -static inline realm::Timestamp RLMTimestampForNSDate(__unsafe_unretained NSDate *const date) { - auto timeInterval = date.timeIntervalSinceReferenceDate; - if (isnan(timeInterval)) - return {0, 0}; // Arbitrary choice - - // Clamp dates that we can't represent as a Timestamp to the maximum value - if (timeInterval >= std::numeric_limits::max() - NSTimeIntervalSince1970) - return {std::numeric_limits::max(), 1'000'000'000 - 1}; - if (timeInterval - NSTimeIntervalSince1970 < std::numeric_limits::min()) - return {std::numeric_limits::min(), -1'000'000'000 + 1}; - - auto seconds = static_cast(timeInterval); - auto nanoseconds = static_cast((timeInterval - seconds) * 1'000'000'000.0); - seconds += static_cast(NSTimeIntervalSince1970); - - // Seconds and nanoseconds have to have the same sign - if (nanoseconds < 0 && seconds > 0) { - nanoseconds += 1'000'000'000; - --seconds; - } - return {seconds, nanoseconds}; -} - -static inline NSUInteger RLMConvertNotFound(size_t index) { - return index == realm::not_found ? NSNotFound : index; -} - -id RLMMixedToObjc(realm::Mixed const& value); - -// For unit testing purposes, allow an Objective-C class named FakeObject to also be used -// as the base class of managed objects. This allows for testing invalid schemas. -void RLMSetTreatFakeObjectAsRLMObject(BOOL flag); - -// Given a bundle identifier, return the base directory on the disk within which Realm database and support files should -// be stored. -NSString *RLMDefaultDirectoryForBundleIdentifier(NSString *bundleIdentifier); diff --git a/Example/Pods/Realm/include/Realm.h b/Example/Pods/Realm/include/Realm.h deleted file mode 100644 index fa299d6..0000000 --- a/Example/Pods/Realm/include/Realm.h +++ /dev/null @@ -1,38 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2014 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 - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import diff --git a/Example/Pods/Realm/include/binding_context.hpp b/Example/Pods/Realm/include/binding_context.hpp deleted file mode 100644 index be31a5c..0000000 --- a/Example/Pods/Realm/include/binding_context.hpp +++ /dev/null @@ -1,160 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef BINDING_CONTEXT_HPP -#define BINDING_CONTEXT_HPP - -#include "index_set.hpp" - -#include -#include - -namespace realm { -// BindingContext is the extension point for adding binding-specific behavior to -// a SharedRealm. It can be used to store additonal data associated with the -// Realm which is needed by the binding, and there are several methods which -// can be overridden to receive notifications of state changes within the Realm. -// -// A simple implementation which lets the user register functions to be -// called on refresh could look like the following: -// -// class BindingContextImplementation : public BindingContext { -// public: -// // A token returned from add_notification that can be used to remove the -// // notification later -// struct token : private std::list>::iterator { -// token(std::list>::iterator it) : std::list>::iterator(it) { } -// friend class DelegateImplementation; -// }; -// -// token add_notification(std::function func) -// { -// m_registered_notifications.push_back(std::move(func)); -// return token(std::prev(m_registered_notifications.end())); -// } -// -// void remove_notification(token entry) -// { -// m_registered_notifications.erase(entry); -// } -// -// // Override the did_change method to call each registered notification -// void did_change(std::vector const&, std::vector const&, bool) override -// { -// // Loop oddly so that unregistering a notification from within the -// // registered function works -// for (auto it = m_registered_notifications.begin(); it != m_registered_notifications.end(); ) { -// (*it++)(); -// } -// } -// -// private: -// std::list> m_registered_notifications; -// }; -class BindingContext { -public: - virtual ~BindingContext() = default; - - // If the user adds a notification handler to the Realm, will it ever - // actually be called? - virtual bool can_deliver_notifications() const noexcept { return true; } - - // Called by the Realm when a write transaction is committed to the file by - // a different Realm instance (possibly in a different process) - virtual void changes_available() { } - - struct ObserverState; - - // Override this function if you want to receive detailed information about - // external changes to a specific set of objects. - // This is called before each operation which may advance the read - // transaction to include - // ObserverStates for each row for which detailed change information is - // desired. - virtual std::vector get_observed_rows() { return {}; } - - // Called immediately before the read transaction is advanced if detailed - // change information was requested (by returning a non-empty array from - // get_observed_rows()). - // The observers vector is the vector returned by get_observed_row(), - // updated with change information. The invalidated vector is a list of the - // `info` fields of observed rows which will be deleted. - virtual void will_change(std::vector const& observers, - std::vector const& invalidated); - - // Called immediately after the read transaction version is advanced. Unlike - // will_change(), this is called even if detailed change information was not - // requested or if the Realm is not actually in a read transaction, although - // both vectors will be empty in that case. - virtual void did_change(std::vector const& observers, - std::vector const& invalidated, - bool version_changed=true); - - // Change information for a single field of a row - struct ColumnInfo { - // The index of this column prior to the changes in the tracked - // transaction, or -1 for newly inserted columns. - size_t initial_column_index = -1; - // What kind of change occurred? - // Always Set or None for everything but LinkList columns. - enum class Kind { - None, // No change - Set, // The value or entries at `indices` were assigned to - Insert, // New values were inserted at each of the indices given - Remove, // Values were removed at each of the indices given - SetAll // The entire LinkList has been replaced with a new set of values - } kind = Kind::None; - // The indices where things happened for Set, Insert and Remove on - // LinkList columns. Not used for other types or for None or SetAll. - IndexSet indices; - }; - - // Information about an observed row in a table - // - // Each object which needs detailed change information should have an - // ObserverState entry in the vector returned from get_observed_rows(), with - // the initial table and row indexes set (and optionally the info field). - // The Realm parses the transaction log, and populates the `changes` vector - // in each ObserverState with information about what changes were made. - struct ObserverState { - // Initial table and row which is observed - // May be updated by row insertions and removals - size_t table_ndx; - size_t row_ndx; - - // Opaque userdata for the delegate's use - void* info; - - // Populated with information about which columns were changed - // May be shorter than the actual number of columns if the later columns - // are not modified - std::vector changes; - - // Simple lexographic ordering - friend bool operator<(ObserverState const& lft, ObserverState const& rgt) - { - return std::tie(lft.table_ndx, lft.row_ndx) < std::tie(rgt.table_ndx, rgt.row_ndx); - } - }; -}; - -inline void BindingContext::will_change(std::vector const&, std::vector const&) { } -inline void BindingContext::did_change(std::vector const&, std::vector const&, bool) { } -} // namespace realm - -#endif /* BINDING_CONTEXT_HPP */ diff --git a/Example/Pods/Realm/include/collection_notifications.hpp b/Example/Pods/Realm/include/collection_notifications.hpp deleted file mode 100644 index 06b5cae..0000000 --- a/Example/Pods/Realm/include/collection_notifications.hpp +++ /dev/null @@ -1,178 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 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. -// -//////////////////////////////////////////////////////////////////////////// - -#ifndef REALM_COLLECTION_NOTIFICATIONS_HPP -#define REALM_COLLECTION_NOTIFICATIONS_HPP - -#include "index_set.hpp" -#include "util/atomic_shared_ptr.hpp" - -#include -#include -#include -#include - -namespace realm { -namespace _impl { - class CollectionNotifier; -} - -// A token which keeps an asynchronous query alive -struct NotificationToken { - NotificationToken() = default; - NotificationToken(std::shared_ptr<_impl::CollectionNotifier> notifier, size_t token); - ~NotificationToken(); - - NotificationToken(NotificationToken&&); - NotificationToken& operator=(NotificationToken&&); - - NotificationToken(NotificationToken const&) = delete; - NotificationToken& operator=(NotificationToken const&) = delete; - - void suppress_next(); - -private: - util::AtomicSharedPtr<_impl::CollectionNotifier> m_notifier; - size_t m_token; -}; - -struct CollectionChangeSet { - struct Move { - size_t from; - size_t to; - - bool operator==(Move m) const { return from == m.from && to == m.to; } - }; - - // Indices which were removed from the _old_ collection - IndexSet deletions; - - // Indices in the _new_ collection which are new insertions - IndexSet insertions; - - // Indices of objects in the _old_ collection which were modified - IndexSet modifications; - - // Indices in the _new_ collection which were modified. This will always - // have the same number of indices as `modifications` and conceptually - // represents the same entries, just in different versions of the collection. - // It exists for the sake of code which finds it easier to process - // modifications after processing deletions and insertions rather than before. - IndexSet modifications_new; - - // Rows in the collection which moved. - // - // Every `from` index will also be present in `deletions` and every `to` - // index will be present in `insertions`. - // - // This is currently not reliably calculated for all types of collections. A - // reported move will always actually be a move, but there may also be - // unreported moves which show up only as a delete/insert pair. - std::vector moves; - - bool empty() const - { - return deletions.empty() && insertions.empty() && modifications.empty() - && modifications_new.empty() && moves.empty(); - } -}; - -// A type-erasing wrapper for the callback for collection notifications. Can be -// constructed with either any callable compatible with the signature -// `void (CollectionChangeSet, std::exception_ptr)`, an object with member -// functions `void before(CollectionChangeSet)`, `void after(CollectionChangeSet)`, -// `void error(std::exception_ptr)`, or a pointer to such an object. If a pointer -// is given, the caller is responsible for ensuring that the pointed-to object -// outlives the collection. -class CollectionChangeCallback { -public: - CollectionChangeCallback(std::nullptr_t={}) { } - - template - CollectionChangeCallback(Callback cb) : m_impl(make_impl(std::move(cb))) { } - template - CollectionChangeCallback& operator=(Callback cb) { m_impl = make_impl(std::move(cb)); return *this; } - - // Explicitly default the copy/move constructors as otherwise they'll use - // the above ones and add an extra layer of wrapping - CollectionChangeCallback(CollectionChangeCallback&&) = default; - CollectionChangeCallback(CollectionChangeCallback const&) = default; - CollectionChangeCallback& operator=(CollectionChangeCallback&&) = default; - CollectionChangeCallback& operator=(CollectionChangeCallback const&) = default; - - void before(CollectionChangeSet const& c) { m_impl->before(c); } - void after(CollectionChangeSet const& c) { m_impl->after(c); } - void error(std::exception_ptr e) { m_impl->error(e); } - - explicit operator bool() const { return !!m_impl; } - -private: - struct Base { - virtual void before(CollectionChangeSet const&)=0; - virtual void after(CollectionChangeSet const&)=0; - virtual void error(std::exception_ptr)=0; - }; - - template()(CollectionChangeSet(), std::exception_ptr()))> - std::shared_ptr make_impl(Callback cb) - { - return std::make_shared>(std::move(cb)); - } - - template().after(CollectionChangeSet())), typename = void> - std::shared_ptr make_impl(Callback cb) - { - return std::make_shared>(std::move(cb)); - } - - template().after(CollectionChangeSet())), typename = void> - std::shared_ptr make_impl(Callback* cb) - { - return std::make_shared>(cb); - } - - template - struct Impl : public Base { - T impl; - Impl(T impl) : impl(std::move(impl)) { } - void before(CollectionChangeSet const&) override { } - void after(CollectionChangeSet const& change) override { impl(change, {}); } - void error(std::exception_ptr error) override { impl({}, error); } - }; - template - struct Impl2 : public Base { - T impl; - Impl2(T impl) : impl(std::move(impl)) { } - void before(CollectionChangeSet const& c) override { impl.before(c); } - void after(CollectionChangeSet const& c) override { impl.after(c); } - void error(std::exception_ptr error) override { impl.error(error); } - }; - template - struct Impl3 : public Base { - T* impl; - Impl3(T* impl) : impl(impl) { } - void before(CollectionChangeSet const& c) override { impl->before(c); } - void after(CollectionChangeSet const& c) override { impl->after(c); } - void error(std::exception_ptr error) override { impl->error(error); } - }; - - std::shared_ptr m_impl; -}; -} // namespace realm - -#endif // REALM_COLLECTION_NOTIFICATIONS_HPP diff --git a/Example/Pods/Realm/include/core/realm.hpp b/Example/Pods/Realm/include/core/realm.hpp deleted file mode 100644 index 29e4844..0000000 --- a/Example/Pods/Realm/include/core/realm.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_HPP -#define REALM_HPP - -#include -#include -#include -#include - -#endif // REALM_HPP diff --git a/Example/Pods/Realm/include/core/realm/alloc.hpp b/Example/Pods/Realm/include/core/realm/alloc.hpp deleted file mode 100644 index 97e4965..0000000 --- a/Example/Pods/Realm/include/core/realm/alloc.hpp +++ /dev/null @@ -1,455 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ALLOC_HPP -#define REALM_ALLOC_HPP - -#include -#include -#include - -#include -#include -#include -#include - -namespace realm { - -class Allocator; - -class Replication; - -using ref_type = size_t; - -int_fast64_t from_ref(ref_type) noexcept; -ref_type to_ref(int_fast64_t) noexcept; -int64_t to_int64(size_t value) noexcept; - -class MemRef { -public: - MemRef() noexcept; - ~MemRef() noexcept; - - MemRef(char* addr, ref_type ref, Allocator& alloc) noexcept; - MemRef(ref_type ref, Allocator& alloc) noexcept; - - char* get_addr(); - ref_type get_ref(); - void set_ref(ref_type ref); - void set_addr(char* addr); - -private: - char* m_addr; - ref_type m_ref; -#if REALM_ENABLE_MEMDEBUG - // Allocator that created m_ref. Used to verify that the ref is valid whenever you call - // get_ref()/get_addr and that it e.g. has not been free'ed - const Allocator* m_alloc = nullptr; -#endif -}; - - -/// The common interface for Realm allocators. -/// -/// A Realm allocator must associate a 'ref' to each allocated -/// object and be able to efficiently map any 'ref' to the -/// corresponding memory address. The 'ref' is an integer and it must -/// always be divisible by 8. Also, a value of zero is used to -/// indicate a null-reference, and must therefore never be returned by -/// Allocator::alloc(). -/// -/// The purpose of the 'refs' is to decouple the memory reference from -/// the actual address and thereby allowing objects to be relocated in -/// memory without having to modify stored references. -/// -/// \sa SlabAlloc -class Allocator { -public: - static constexpr int CURRENT_FILE_FORMAT_VERSION = 6; - - /// The specified size must be divisible by 8, and must not be - /// zero. - /// - /// \throw std::bad_alloc If insufficient memory was available. - MemRef alloc(size_t size); - - /// Calls do_realloc(). - /// - /// Note: The underscore has been added because the name `realloc` - /// would conflict with a macro on the Windows platform. - MemRef realloc_(ref_type, const char* addr, size_t old_size, size_t new_size); - - /// Calls do_free(). - /// - /// Note: The underscore has been added because the name `free - /// would conflict with a macro on the Windows platform. - void free_(ref_type, const char* addr) noexcept; - - /// Shorthand for free_(mem.get_ref(), mem.get_addr()). - void free_(MemRef mem) noexcept; - - /// Calls do_translate(). - char* translate(ref_type ref) const noexcept; - - /// Returns true if, and only if the object at the specified 'ref' - /// is in the immutable part of the memory managed by this - /// allocator. The method by which some objects become part of the - /// immuatble part is entirely up to the class that implements - /// this interface. - bool is_read_only(ref_type) const noexcept; - - /// Returns a simple allocator that can be used with free-standing - /// Realm objects (such as a free-standing table). A - /// free-standing object is one that is not part of a Group, and - /// therefore, is not part of an actual database. - static Allocator& get_default() noexcept; - - virtual ~Allocator() noexcept; - - virtual void verify() const = 0; - -#ifdef REALM_DEBUG - /// Terminate the program precisely when the specified 'ref' is - /// freed (or reallocated). You can use this to detect whether the - /// ref is freed (or reallocated), and even to get a stacktrace at - /// the point where it happens. Call watch(0) to stop watching - /// that ref. - void watch(ref_type ref) - { - m_debug_watch = ref; - } -#endif - - Replication* get_replication() noexcept; - - /// \brief The version of the format of the the node structure (in file or - /// in memory) in use by Realm objects associated with this allocator. - /// - /// Every allocator contains a file format version field, which is returned - /// by this function. In some cases (as mentioned below) the file format can - /// change. - /// - /// A value of zero means the the file format is not yet decided. This is - /// only possible for empty Realms where top-ref is zero. - /// - /// For the default allocator (get_default()), the file format version field - /// can never change, is never zero, and is set to whatever - /// Group::get_target_file_format_version_for_session() would return if the - /// original file format version was undecided and the request history type - /// was Replication::hist_None. - /// - /// For the slab allocator (AllocSlab), the file format version field is set - /// to the file format version specified by the attached file (or attached - /// memory buffer) at the time of attachment. If no file (or buffer) is - /// currently attached, the returned value has no meaning. If the Realm file - /// format is later upgraded, the file format version filed must be updated - /// to reflect that fact. - /// - /// In shared mode (when a Realm file is opened via a SharedGroup instance) - /// it can happen that the file format is upgraded asyncronously (via - /// another SharedGroup instance), and in that case the file format version - /// field of the allocator can get out of date, but only for a short - /// while. It is always garanteed to be, and remain up to date after the - /// opening process completes (when SharedGroup::do_open() returns). - /// - /// An empty Realm file (one whose top-ref is zero) may specify a file - /// format version of zero to indicate that the format is not yet - /// decided. In that case, this function will return zero immediately after - /// AllocSlab::attach_file() returns. It shall be guaranteed, however, that - /// the zero is changed to a proper file format version before the opening - /// process completes (Group::open() or SharedGroup::open()). It is the duty - /// of the caller of AllocSlab::attach_file() to ensure this. - /// - /// File format versions: - /// - /// 1 Initial file format version - /// - /// 2 Various changes. - /// - /// 3 Supporting null on string columns broke the file format in following - /// way: Index appends an 'X' character to all strings except the null - /// string, to be able to distinguish between null and empty - /// string. Bumped to 3 because of null support of String columns and - /// because of new format of index. - /// - /// 4 Introduction of optional in-Realm history of changes (additional - /// entries in Group::m_top). Since this change is not forward - /// compatible, the file format version had to be bumped. This change is - /// implemented in a way that achieves backwards compatibility with - /// version 3 (and in turn with version 2). - /// - /// 5 Introduced the new Timestamp column type that replaces DateTime. - /// When opening an older database file, all DateTime columns will be - /// automatically upgraded Timestamp columns. - /// - /// 6 Introduced a new structure for the StringIndex. Moved the commit - /// logs into the Realm file. Changes to the transaction log format - /// including reshuffling instructions. This is the format used in - /// milestone 2.0.0. - /// - /// IMPORTANT: When introducing a new file format version, be sure to review - /// the file validity checks in AllocSlab::validate_buffer(), the file - /// format selection logic in - /// Group::get_target_file_format_version_for_session(), and the file format - /// upgrade logic in Group::upgrade_file_format(). - int get_file_format_version() const noexcept; - -protected: - size_t m_baseline = 0; // Separation line between immutable and mutable refs. - - Replication* m_replication = nullptr; - - /// See get_file_format_version(). - int m_file_format_version = 0; - - ref_type m_debug_watch = 0; - - /// The specified size must be divisible by 8, and must not be - /// zero. - /// - /// \throw std::bad_alloc If insufficient memory was available. - virtual MemRef do_alloc(size_t size) = 0; - - /// The specified size must be divisible by 8, and must not be - /// zero. - /// - /// The default version of this function simply allocates a new - /// chunk of memory, copies over the old contents, and then frees - /// the old chunk. - /// - /// \throw std::bad_alloc If insufficient memory was available. - virtual MemRef do_realloc(ref_type, const char* addr, size_t old_size, size_t new_size) = 0; - - /// Release the specified chunk of memory. - virtual void do_free(ref_type, const char* addr) noexcept = 0; - - /// Map the specified \a ref to the corresponding memory - /// address. Note that if is_read_only(ref) returns true, then the - /// referenced object is to be considered immutable, and it is - /// then entirely the responsibility of the caller that the memory - /// is not modified by way of the returned memory pointer. - virtual char* do_translate(ref_type ref) const noexcept = 0; - - Allocator() noexcept; - - // FIXME: This really doesn't belong in an allocator, but it is the best - // place for now, because every table has a pointer leading here. It would - // be more obvious to place it in Group, but that would add a runtime overhead, - // and access is time critical. - // - // This means that multiple threads that allocate Realm objects through the - // default allocator will share this variable, which is a logical design flaw - // that can make sync_if_needed() re-run queries even though it is not required. - // It must be atomic because it's shared. - std::atomic m_table_versioning_counter; - - /// Bump the global version counter. This method should be called when - /// version bumping is initiated. Then following calls to should_propagate_version() - /// can be used to prune the version bumping. - uint_fast64_t bump_global_version() noexcept; - - /// Determine if the "local_version" is out of sync, so that it should - /// be updated. In that case: also update it. Called from Table::bump_version - /// to control propagation of version updates on tables within the group. - bool should_propagate_version(uint_fast64_t& local_version) noexcept; - - friend class Table; - friend class Group; -}; - -inline uint_fast64_t Allocator::bump_global_version() noexcept -{ - ++m_table_versioning_counter; - return m_table_versioning_counter; -} - - -inline bool Allocator::should_propagate_version(uint_fast64_t& local_version) noexcept -{ - if (local_version != m_table_versioning_counter) { - local_version = m_table_versioning_counter; - return true; - } - else { - return false; - } -} - - -// Implementation: - -inline int_fast64_t from_ref(ref_type v) noexcept -{ - // Check that v is divisible by 8 (64-bit aligned). - REALM_ASSERT_DEBUG(v % 8 == 0); - - static_assert(std::is_same::value, - "If ref_type changes, from_ref and to_ref should probably be updated"); - - // Make sure that we preserve the bit pattern of the ref_type (without sign extension). - return util::from_twos_compl(uint_fast64_t(v)); -} - -inline ref_type to_ref(int_fast64_t v) noexcept -{ - // Check that v is divisible by 8 (64-bit aligned). - REALM_ASSERT_DEBUG(v % 8 == 0); - - // C++11 standard, paragraph 4.7.2 [conv.integral]: - // If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source - // integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s - // complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is - // no truncation). — end note ] - static_assert(std::is_unsigned::value, - "If ref_type changes, from_ref and to_ref should probably be updated"); - return ref_type(v); -} - -inline int64_t to_int64(size_t value) noexcept -{ - // FIXME: Enable once we get clang warning flags correct - // REALM_ASSERT_DEBUG(value <= std::numeric_limits::max()); - return static_cast(value); -} - - -inline MemRef::MemRef() noexcept - : m_addr(nullptr) - , m_ref(0) -{ -} - -inline MemRef::~MemRef() noexcept -{ -} - -inline MemRef::MemRef(char* addr, ref_type ref, Allocator& alloc) noexcept - : m_addr(addr) - , m_ref(ref) -{ - static_cast(alloc); -#if REALM_ENABLE_MEMDEBUG - m_alloc = &alloc; -#endif -} - -inline MemRef::MemRef(ref_type ref, Allocator& alloc) noexcept - : m_addr(alloc.translate(ref)) - , m_ref(ref) -{ - static_cast(alloc); -#if REALM_ENABLE_MEMDEBUG - m_alloc = &alloc; -#endif -} - -inline char* MemRef::get_addr() -{ -#if REALM_ENABLE_MEMDEBUG - // Asserts if the ref has been freed - m_alloc->translate(m_ref); -#endif - return m_addr; -} - -inline ref_type MemRef::get_ref() -{ -#if REALM_ENABLE_MEMDEBUG - // Asserts if the ref has been freed - m_alloc->translate(m_ref); -#endif - return m_ref; -} - -inline void MemRef::set_ref(ref_type ref) -{ -#if REALM_ENABLE_MEMDEBUG - // Asserts if the ref has been freed - m_alloc->translate(ref); -#endif - m_ref = ref; -} - -inline void MemRef::set_addr(char* addr) -{ - m_addr = addr; -} - -inline MemRef Allocator::alloc(size_t size) -{ - return do_alloc(size); -} - -inline MemRef Allocator::realloc_(ref_type ref, const char* addr, size_t old_size, size_t new_size) -{ -#ifdef REALM_DEBUG - if (ref == m_debug_watch) - REALM_TERMINATE("Allocator watch: Ref was reallocated"); -#endif - return do_realloc(ref, addr, old_size, new_size); -} - -inline void Allocator::free_(ref_type ref, const char* addr) noexcept -{ -#ifdef REALM_DEBUG - if (ref == m_debug_watch) - REALM_TERMINATE("Allocator watch: Ref was freed"); -#endif - return do_free(ref, addr); -} - -inline void Allocator::free_(MemRef mem) noexcept -{ - free_(mem.get_ref(), mem.get_addr()); -} - -inline char* Allocator::translate(ref_type ref) const noexcept -{ - return do_translate(ref); -} - -inline bool Allocator::is_read_only(ref_type ref) const noexcept -{ - REALM_ASSERT_DEBUG(ref != 0); - REALM_ASSERT_DEBUG(m_baseline != 0); // Attached SlabAlloc - return ref < m_baseline; -} - -inline Allocator::Allocator() noexcept -{ - m_table_versioning_counter = 0; -} - -inline Allocator::~Allocator() noexcept -{ -} - -inline Replication* Allocator::get_replication() noexcept -{ - return m_replication; -} - -inline int Allocator::get_file_format_version() const noexcept -{ - return m_file_format_version; -} - - -} // namespace realm - -#endif // REALM_ALLOC_HPP diff --git a/Example/Pods/Realm/include/core/realm/alloc_slab.hpp b/Example/Pods/Realm/include/core/realm/alloc_slab.hpp deleted file mode 100644 index 34aa9b1..0000000 --- a/Example/Pods/Realm/include/core/realm/alloc_slab.hpp +++ /dev/null @@ -1,592 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ALLOC_SLAB_HPP -#define REALM_ALLOC_SLAB_HPP - -#include // unint8_t etc -#include -#include -#include - -#include -#include -#include -#include - -namespace realm { - -// Pre-declarations -class Group; -class GroupWriter; - - -/// Thrown by Group and SharedGroup constructors if the specified file -/// (or memory buffer) does not appear to contain a valid Realm -/// database. -struct InvalidDatabase; - - -/// The allocator that is used to manage the memory of a Realm -/// group, i.e., a Realm database. -/// -/// Optionally, it can be attached to an pre-existing database (file -/// or memory buffer) which then becomes an immuatble part of the -/// managed memory. -/// -/// To attach a slab allocator to a pre-existing database, call -/// attach_file() or attach_buffer(). To create a new database -/// in-memory, call attach_empty(). -/// -/// For efficiency, this allocator manages its mutable memory as a set -/// of slabs. -class SlabAlloc : public Allocator { -public: - ~SlabAlloc() noexcept override; - SlabAlloc(); - - /// \struct Config - /// \brief Storage for combining setup flags for initialization to - /// the SlabAlloc. - /// - /// \var Config::is_shared - /// Must be true if, and only if we are called on behalf of SharedGroup. - /// - /// \var Config::read_only - /// Open the file in read-only mode. This implies \a Config::no_create. - /// - /// \var Config::no_create - /// Fail if the file does not already exist. - /// - /// \var Config::skip_validate - /// Skip validation of file header. In a - /// set of overlapping SharedGroups, only the first one (the one - /// that creates/initlializes the coordination file) may validate - /// the header, otherwise it will result in a race condition. - /// - /// \var Config::encryption_key - /// 32-byte key to use to encrypt and decrypt the backing storage, - /// or nullptr to disable encryption. - /// - /// \var Config::session_initiator - /// If set, the caller is the session initiator and - /// guarantees exclusive access to the file. If attaching in - /// read/write mode, the file is modified: files on streaming form - /// is changed to non-streaming form, and if needed the file size - /// is adjusted to match mmap boundaries. - /// Must be set to false if is_shared is false. - /// - /// \var Config::clear_file - /// Always initialize the file as if it was a newly - /// created file and ignore any pre-existing contents. Requires that - /// Config::session_initiator be true as well. - struct Config { - bool is_shared = false; - bool read_only = false; - bool no_create = false; - bool skip_validate = false; - bool session_initiator = false; - bool clear_file = false; - const char* encryption_key = nullptr; - }; - - struct Retry { - }; - - /// \brief Attach this allocator to the specified file. - /// - /// It is an error if this function is called at a time where the specified - /// Realm file (file system inode) is modified asynchronously. - /// - /// In non-shared mode (when this function is called on behalf of a - /// free-standing Group instance), it is the responsibility of the - /// application to ensure that the Realm file is not modified concurrently - /// from any other thread or process. - /// - /// In shared mode (when this function is called on behalf of a SharedGroup - /// instance), the caller (SharedGroup::do_open()) must take steps to ensure - /// cross-process mutual exclusion. - /// - /// If the attached file contains an empty Realm (one whose top-ref is - /// zero), the file format version may remain undecided upon return from - /// this function. The file format is undecided if, and only if - /// get_file_format_version() returns zero. The caller is required to check - /// for this case, and decide on a file format version. This must happen - /// before the Realm opening process completes, and the decided file format - /// must be set in the allocator by calling set_file_format_version(). - /// - /// Except for \a path, the parameters are passed in through a - /// configuration object. - /// - /// \return The `ref` of the root node, or zero if there is none. - /// - /// Please note that attach_file can fail to attach to a file due to a - /// collision with a writer extending the file. This can only happen if the - /// caller is *not* the session initiator. When this happens, attach_file() - /// throws SlabAlloc::Retry, and the caller must retry the call. The caller - /// should check if it has become the session initiator before retrying. - /// This can happen if the conflicting thread (or process) terminates or - /// crashes before the next retry. - /// - /// \throw util::File::AccessError - /// \throw SlabAlloc::Retry - ref_type attach_file(const std::string& path, Config& cfg); - - /// Get the attached file. Only valid when called on an allocator with - /// an attached file. - util::File& get_file(); - - /// Attach this allocator to the specified memory buffer. - /// - /// If the attached buffer contains an empty Realm (one whose top-ref is - /// zero), the file format version may remain undecided upon return from - /// this function. The file format is undecided if, and only if - /// get_file_format_version() returns zero. The caller is required to check - /// for this case, and decide on a file format version. This must happen - /// before the Realm opening process completes, and the decided file format - /// must be set in the allocator by calling set_file_format_version(). - /// - /// It is an error to call this function on an attached - /// allocator. Doing so will result in undefined behavor. - /// - /// \return The `ref` of the root node, or zero if there is none. - /// - /// \sa own_buffer() - /// - /// \throw InvalidDatabase - ref_type attach_buffer(const char* data, size_t size); - - /// Reads file format from file header. Must be called from within a write - /// transaction. - int get_committed_file_format_version() const noexcept; - - /// Attach this allocator to an empty buffer. - /// - /// Upon return from this function, the file format is undecided - /// (get_file_format_version() returns zero). The caller is required to - /// decide on a file format version. This must happen before the Realm - /// opening process completes, and the decided file format must be set in - /// the allocator by calling set_file_format_version(). - /// - /// It is an error to call this function on an attached - /// allocator. Doing so will result in undefined behavor. - void attach_empty(); - - /// Detach from a previously attached file or buffer. - /// - /// This function does not reset free space tracking. To - /// completely reset the allocator, you must also call - /// reset_free_space_tracking(). - /// - /// This function has no effect if the allocator is already in the - /// detached state (idempotency). - void detach() noexcept; - - class DetachGuard; - - /// If a memory buffer has been attached using attach_buffer(), - /// mark it as owned by this slab allocator. Behaviour is - /// undefined if this function is called on a detached allocator, - /// one that is not attached using attach_buffer(), or one for - /// which this function has already been called during the latest - /// attachment. - void own_buffer() noexcept; - - /// Returns true if, and only if this allocator is currently - /// in the attached state. - bool is_attached() const noexcept; - - /// Returns true if, and only if this allocator is currently in - /// the attached state and attachment was not established using - /// attach_empty(). - bool nonempty_attachment() const noexcept; - - /// Reserve disk space now to avoid allocation errors at a later - /// point in time, and to minimize on-disk fragmentation. In some - /// cases, less fragmentation translates into improved - /// performance. On flash or SSD-drives this is likely a waste. - /// - /// Note: File::prealloc() may misbehave under race conditions (see - /// documentation of File::prealloc()). For that reason, to avoid race - /// conditions, when this allocator is used in a transactional mode, this - /// function may be called only when the caller has exclusive write - /// access. In non-transactional mode it is the responsibility of the user - /// to ensure non-concurrent file mutation. - /// - /// This function will call File::sync(). - /// - /// It is an error to call this function on an allocator that is not - /// attached to a file. Doing so will result in undefined behavior. - void resize_file(size_t new_file_size); - - /// Reserve disk space now to avoid allocation errors at a later point in - /// time, and to minimize on-disk fragmentation. In some cases, less - /// fragmentation translates into improved performance. On SSD-drives - /// preallocation is likely a waste. - /// - /// When supported by the system, a call to this function will make the - /// database file at least as big as the specified size, and cause space on - /// the target device to be allocated (note that on many systems on-disk - /// allocation is done lazily by default). If the file is already bigger - /// than the specified size, the size will be unchanged, and on-disk - /// allocation will occur only for the initial section that corresponds to - /// the specified size. On systems that do not support preallocation, this - /// function has no effect. To know whether preallocation is supported by - /// Realm on your platform, call util::File::is_prealloc_supported(). - /// - /// This function will call File::sync() if it changes the size of the file. - /// - /// It is an error to call this function on an allocator that is not - /// attached to a file. Doing so will result in undefined behavior. - void reserve_disk_space(size_t size_in_bytes); - - /// Get the size of the attached database file or buffer in number - /// of bytes. This size is not affected by new allocations. After - /// attachment, it can only be modified by a call to remap(). - /// - /// It is an error to call this function on a detached allocator, - /// or one that was attached using attach_empty(). Doing so will - /// result in undefined behavior. - size_t get_baseline() const noexcept; - - /// Get the total amount of managed memory. This is the baseline plus the - /// sum of the sizes of the allocated slabs. It includes any free space. - /// - /// It is an error to call this function on a detached - /// allocator. Doing so will result in undefined behavior. - size_t get_total_size() const noexcept; - - /// Mark all mutable memory (ref-space outside the attached file) as free - /// space. - void reset_free_space_tracking(); - - /// Remap the attached file such that a prefix of the specified - /// size becomes available in memory. If sucessfull, - /// get_baseline() will return the specified new file size. - /// - /// It is an error to call this function on a detached allocator, - /// or one that was not attached using attach_file(). Doing so - /// will result in undefined behavior. - /// - /// The file_size argument must be aligned to a *section* boundary: - /// The database file is logically split into sections, each section - /// guaranteed to be mapped as a contiguous address range. The allocation - /// of memory in the file must ensure that no allocation crosses the - /// boundary between two sections. - void remap(size_t file_size); - - /// Returns true initially, and after a call to reset_free_space_tracking() - /// up until the point of the first call to SlabAlloc::alloc(). Note that a - /// call to SlabAlloc::alloc() corresponds to a mutation event. - bool is_free_space_clean() const noexcept; - - /// \brief Update the file format version field of the allocator. - /// - /// This must be done during the opening of the Realm if the stored file - /// format version is zero (empty Realm), or after the file format is - /// upgraded. - /// - /// Note that this does not modify the attached file, only the "cached" - /// value subsequenty returned by get_file_format_version(). - /// - /// \sa get_file_format_version() - void set_file_format_version(int) noexcept; - - void verify() const override; -#ifdef REALM_DEBUG - void enable_debug(bool enable) - { - m_debug_out = enable; - } - bool is_all_free() const; - void print() const; -#endif - struct MappedFile; - -protected: - MemRef do_alloc(const size_t size) override; - MemRef do_realloc(ref_type, const char*, size_t old_size, size_t new_size) override; - // FIXME: It would be very nice if we could detect an invalid free operation in debug mode - void do_free(ref_type, const char*) noexcept override; - char* do_translate(ref_type) const noexcept override; - void invalidate_cache() noexcept; - -private: - enum AttachMode { - attach_None, // Nothing is attached - attach_OwnedBuffer, // We own the buffer (m_data = nullptr for empty buffer) - attach_UsersBuffer, // We do not own the buffer - attach_SharedFile, // On behalf of SharedGroup - attach_UnsharedFile // Not on behalf of SharedGroup - }; - - // A slab is a dynamically allocated contiguous chunk of memory used to - // extend the amount of space available for database node - // storage. Inter-node references are represented as file offsets - // (a.k.a. "refs"), and each slab creates an apparently seamless extension - // of this file offset addressable space. Slabes are stored as rows in the - // Slabs table in order of ascending file offsets. - struct Slab { - ref_type ref_end; - char* addr; - }; - struct Chunk { - ref_type ref; - size_t size; - }; - - // Values of each used bit in m_flags - enum { - flags_SelectBit = 1, - }; - - // 24 bytes - struct Header { - uint64_t m_top_ref[2]; // 2 * 8 bytes - // Info-block 8-bytes - uint8_t m_mnemonic[4]; // "T-DB" - uint8_t m_file_format[2]; // See `library_file_format` - uint8_t m_reserved; - // bit 0 of m_flags is used to select between the two top refs. - uint8_t m_flags; - }; - - // 16 bytes - struct StreamingFooter { - uint64_t m_top_ref; - uint64_t m_magic_cookie; - }; - - static_assert(sizeof(Header) == 24, "Bad header size"); - static_assert(sizeof(StreamingFooter) == 16, "Bad footer size"); - - static const Header empty_file_header; - static void init_streaming_header(Header*, int file_format_version); - - static const uint_fast64_t footer_magic_cookie = 0x3034125237E526C8ULL; - - // The mappings are shared, if they are from a file - std::shared_ptr m_file_mappings; - - // We are caching local copies of all the additional mappings to allow - // for lock-free lookup during ref->address translation (we do not need - // to cache the first mapping, because it is immutable) (well, all the - // mappings are immutable, but the array holding them is not - it may - // have to be relocated) - std::unique_ptr>[]> m_local_mappings; - size_t m_num_local_mappings = 0; - - const char* m_data = nullptr; - size_t m_initial_chunk_size = 0; - size_t m_initial_section_size = 0; - int m_section_shifts = 0; - std::unique_ptr m_section_bases; - size_t m_num_section_bases = 0; - AttachMode m_attach_mode = attach_None; - bool m_file_on_streaming_form = false; - enum FeeeSpaceState { - free_space_Clean, - free_space_Dirty, - free_space_Invalid, - }; - - /// When set to free_space_Invalid, the free lists are no longer - /// up-to-date. This happens if do_free() or - /// reset_free_space_tracking() fails, presumably due to - /// std::bad_alloc being thrown during updating of the free space - /// list. In this this case, alloc(), realloc_(), and - /// get_free_read_only() must throw. This member is deliberately - /// placed here (after m_attach_mode) in the hope that it leads to - /// less padding between members due to alignment requirements. - FeeeSpaceState m_free_space_state = free_space_Clean; - - typedef std::vector slabs; - typedef std::vector chunks; - slabs m_slabs; - chunks m_free_space; - chunks m_free_read_only; - - bool m_debug_out = false; - struct hash_entry { - ref_type ref = 0; - const char* addr = nullptr; - size_t version = 0; - }; - mutable hash_entry cache[256]; - mutable size_t version = 1; - - /// Throws if free-lists are no longer valid. - void consolidate_free_read_only(); - /// Throws if free-lists are no longer valid. - const chunks& get_free_read_only() const; - - /// Throws InvalidDatabase if the file is not a Realm file, if the file is - /// corrupted, or if the specified encryption key is incorrect. This - /// function will not detect all forms of corruption, though. - void validate_buffer(const char* data, size_t len, const std::string& path, bool is_shared); - - /// Read the top_ref from the given buffer and set m_file_on_streaming_form - /// if the buffer contains a file in streaming form - ref_type get_top_ref(const char* data, size_t len); - - class ChunkRefEq; - class ChunkRefEndEq; - class SlabRefEndEq; - static bool ref_less_than_slab_ref_end(ref_type, const Slab&) noexcept; - - Replication* get_replication() const noexcept - { - return m_replication; - } - void set_replication(Replication* r) noexcept - { - m_replication = r; - } - - /// Returns the first section boundary *above* the given position. - size_t get_upper_section_boundary(size_t start_pos) const noexcept; - - /// Returns the first section boundary *at or below* the given position. - size_t get_lower_section_boundary(size_t start_pos) const noexcept; - - /// Returns true if the given position is at a section boundary - bool matches_section_boundary(size_t pos) const noexcept; - - /// Returns the index of the section holding a given address. - /// The section index is determined solely by the minimal section size, - /// and does not necessarily reflect the mapping. A mapping may - /// cover multiple sections - the initial mapping often does. - size_t get_section_index(size_t pos) const noexcept; - - /// Reverse: get the base offset of a section at a given index. Since the - /// computation is very time critical, this method just looks it up in - /// a table. The actual computation and setup of that table is done - /// during initialization with the help of compute_section_base() below. - inline size_t get_section_base(size_t index) const noexcept; - - /// Actually compute the starting offset of a section. Only used to initialize - /// a table of predefined results, which are then used by get_section_base(). - size_t compute_section_base(size_t index) const noexcept; - - /// Find a possible allocation of 'request_size' that will fit into a section - /// which is inside the range from 'start_pos' to 'start_pos'+'free_chunk_size' - /// If found return the position, if not return 0. - size_t find_section_in_range(size_t start_pos, size_t free_chunk_size, size_t request_size) const noexcept; - - friend class Group; - friend class GroupWriter; -}; - -inline void SlabAlloc::invalidate_cache() noexcept -{ - ++version; -} - -class SlabAlloc::DetachGuard { -public: - DetachGuard(SlabAlloc& alloc) noexcept - : m_alloc(&alloc) - { - } - ~DetachGuard() noexcept; - SlabAlloc* release() noexcept; - -private: - SlabAlloc* m_alloc; -}; - - -// Implementation: - -struct InvalidDatabase : util::File::AccessError { - InvalidDatabase(const std::string& msg, const std::string& path) - : util::File::AccessError(msg, path) - { - } -}; - -inline void SlabAlloc::own_buffer() noexcept -{ - REALM_ASSERT_3(m_attach_mode, ==, attach_UsersBuffer); - REALM_ASSERT(m_data); - REALM_ASSERT(m_file_mappings == nullptr); - m_attach_mode = attach_OwnedBuffer; -} - -inline bool SlabAlloc::is_attached() const noexcept -{ - return m_attach_mode != attach_None; -} - -inline bool SlabAlloc::nonempty_attachment() const noexcept -{ - return is_attached() && m_data; -} - -inline size_t SlabAlloc::get_baseline() const noexcept -{ - REALM_ASSERT_DEBUG(is_attached()); - return m_baseline; -} - -inline bool SlabAlloc::is_free_space_clean() const noexcept -{ - return m_free_space_state == free_space_Clean; -} - -inline SlabAlloc::DetachGuard::~DetachGuard() noexcept -{ - if (m_alloc) - m_alloc->detach(); -} - -inline SlabAlloc* SlabAlloc::DetachGuard::release() noexcept -{ - SlabAlloc* alloc = m_alloc; - m_alloc = nullptr; - return alloc; -} - -inline bool SlabAlloc::ref_less_than_slab_ref_end(ref_type ref, const Slab& slab) noexcept -{ - return ref < slab.ref_end; -} - -inline size_t SlabAlloc::get_upper_section_boundary(size_t start_pos) const noexcept -{ - return get_section_base(1 + get_section_index(start_pos)); -} - -inline size_t SlabAlloc::get_lower_section_boundary(size_t start_pos) const noexcept -{ - return get_section_base(get_section_index(start_pos)); -} - -inline bool SlabAlloc::matches_section_boundary(size_t pos) const noexcept -{ - return pos == get_lower_section_boundary(pos); -} - -inline size_t SlabAlloc::get_section_base(size_t index) const noexcept -{ - return m_section_bases[index]; -} - -} // namespace realm - -#endif // REALM_ALLOC_SLAB_HPP diff --git a/Example/Pods/Realm/include/core/realm/array.hpp b/Example/Pods/Realm/include/core/realm/array.hpp deleted file mode 100644 index fdad46e..0000000 --- a/Example/Pods/Realm/include/core/realm/array.hpp +++ /dev/null @@ -1,3055 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -/* -Searching: The main finding function is: - template - void find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState *state, Callback callback) const - - cond: One of Equal, NotEqual, Greater, etc. classes - Action: One of act_ReturnFirst, act_FindAll, act_Max, act_CallbackIdx, etc, constants - Callback: Optional function to call for each search result. Will be called if action == act_CallbackIdx - - find() will call find_action_pattern() or find_action() that again calls match() for each search result which - optionally calls callback(): - - find() -> find_action() -------> bool match() -> bool callback() - | ^ - +-> find_action_pattern()----+ - - If callback() returns false, find() will exit, otherwise it will keep searching remaining items in array. -*/ - -#ifndef REALM_ARRAY_HPP -#define REALM_ARRAY_HPP - -#include -#include // size_t -#include -#include -#include -#include - -#include // unint8_t etc - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - MMX: mmintrin.h - SSE: xmmintrin.h - SSE2: emmintrin.h - SSE3: pmmintrin.h - SSSE3: tmmintrin.h - SSE4A: ammintrin.h - SSE4.1: smmintrin.h - SSE4.2: nmmintrin.h -*/ -#ifdef REALM_COMPILER_SSE -#include // SSE2 -#include // SSE42 -#endif - -namespace realm { - -enum Action { - act_ReturnFirst, - act_Sum, - act_Max, - act_Min, - act_Count, - act_FindAll, - act_CallIdx, - act_CallbackIdx, - act_CallbackVal, - act_CallbackNone, - act_CallbackBoth, - act_Average -}; - -template -inline T no0(T v) -{ - return v == 0 ? 1 : v; -} - -/// Special index value. It has various meanings depending on -/// context. It is returned by some search functions to indicate 'not -/// found'. It is similar in function to std::string::npos. -const size_t npos = size_t(-1); - -// Maximum number of bytes that the payload of an array can be -const size_t max_array_payload = 0x00ffffffL; - -/// Alias for realm::npos. -const size_t not_found = npos; - -// Pre-definitions -class Array; -class StringColumn; -class GroupWriter; -template -class QueryState; -namespace _impl { -class ArrayWriterBase; -} - - -#ifdef REALM_DEBUG -struct MemStats { - size_t allocated = 0; - size_t used = 0; - size_t array_count = 0; -}; -template -std::basic_ostream& operator<<(std::basic_ostream& out, MemStats stats); -#endif - - -// Stores a value obtained from Array::get(). It is a ref if the least -// significant bit is clear, otherwise it is a tagged integer. A tagged interger -// is obtained from a logical integer value by left shifting by one bit position -// (multiplying by two), and then setting the least significant bit to -// one. Clearly, this means that the maximum value that can be stored as a -// tagged integer is 2**63 - 1. -class RefOrTagged { -public: - bool is_ref() const noexcept; - bool is_tagged() const noexcept; - ref_type get_as_ref() const noexcept; - uint_fast64_t get_as_int() const noexcept; - - static RefOrTagged make_ref(ref_type) noexcept; - static RefOrTagged make_tagged(uint_fast64_t) noexcept; - -private: - int_fast64_t m_value; - RefOrTagged(int_fast64_t) noexcept; - friend class Array; -}; - - -class ArrayParent { -public: - virtual ~ArrayParent() noexcept - { - } - -protected: - virtual void update_child_ref(size_t child_ndx, ref_type new_ref) = 0; - - virtual ref_type get_child_ref(size_t child_ndx) const noexcept = 0; - - // Used only by Array::to_dot(). - virtual std::pair get_to_dot_parent(size_t ndx_in_parent) const = 0; - - friend class Array; -}; - -struct TreeInsertBase { - size_t m_split_offset; - size_t m_split_size; -}; - -/// Provides access to individual array nodes of the database. -/// -/// This class serves purely as an accessor, it assumes no ownership of the -/// referenced memory. -/// -/// An array accessor can be in one of two states: attached or unattached. It is -/// in the attached state if, and only if is_attached() returns true. Most -/// non-static member functions of this class have undefined behaviour if the -/// accessor is in the unattached state. The exceptions are: is_attached(), -/// detach(), create(), init_from_ref(), init_from_mem(), init_from_parent(), -/// has_parent(), get_parent(), set_parent(), get_ndx_in_parent(), -/// set_ndx_in_parent(), adjust_ndx_in_parent(), and get_ref_from_parent(). -/// -/// An array accessor contains information about the parent of the referenced -/// array node. This 'reverse' reference is not explicitely present in the -/// underlying node hierarchy, but it is needed when modifying an array. A -/// modification may lead to relocation of the underlying array node, and the -/// parent must be updated accordingly. Since this applies recursivly all the -/// way to the root node, it is essential that the entire chain of parent -/// accessors is constructed and propperly maintained when a particular array is -/// modified. -/// -/// The parent reference (`pointer to parent`, `index in parent`) is updated -/// independently from the state of attachment to an underlying node. In -/// particular, the parent reference remains valid and is unannfected by changes -/// in attachment. These two aspects of the state of the accessor is updated -/// independently, and it is entirely the responsibility of the caller to update -/// them such that they are consistent with the underlying node hierarchy before -/// calling any method that modifies the underlying array node. -/// -/// FIXME: This class currently has fragments of ownership, in particular the -/// constructors that allocate underlying memory. On the other hand, the -/// destructor never frees the memory. This is a problematic situation, because -/// it so easily becomes an obscure source of leaks. There are three options for -/// a fix of which the third is most attractive but hardest to implement: (1) -/// Remove all traces of ownership semantics, that is, remove the constructors -/// that allocate memory, but keep the trivial copy constructor. For this to -/// work, it is important that the constness of the accessor has nothing to do -/// with the constness of the underlying memory, otherwise constness can be -/// violated simply by copying the accessor. (2) Disallov copying but associate -/// the constness of the accessor with the constness of the underlying -/// memory. (3) Provide full ownership semantics like is done for Table -/// accessors, and provide a proper copy constructor that really produces a copy -/// of the array. For this to work, the class should assume ownership if, and -/// only if there is no parent. A copy produced by a copy constructor will not -/// have a parent. Even if the original was part of a database, the copy will be -/// free-standing, that is, not be part of any database. For intra, or inter -/// database copying, one would have to also specify the target allocator. -class Array : public ArrayParent { -public: - // void state_init(int action, QueryState *state); - // bool match(int action, size_t index, int64_t value, QueryState *state); - - /// Create an array accessor in the unattached state. - explicit Array(Allocator&) noexcept; - - ~Array() noexcept override - { - } - - enum Type { - type_Normal, - - /// This array is the main array of an innner node of a B+-tree as used - /// in table columns. - type_InnerBptreeNode, - - /// This array may contain refs to subarrays. An element whose least - /// significant bit is zero, is a ref pointing to a subarray. An element - /// whose least significant bit is one, is just a value. It is the - /// responsibility of the application to ensure that non-ref values have - /// their least significant bit set. This will generally be done by - /// shifting the desired vlue to the left by one bit position, and then - /// setting the vacated bit to one. - type_HasRefs - }; - - /// Create a new integer array of the specified type and size, and filled - /// with the specified value, and attach this accessor to it. This does not - /// modify the parent reference information of this accessor. - /// - /// Note that the caller assumes ownership of the allocated underlying - /// node. It is not owned by the accessor. - void create(Type, bool context_flag = false, size_t size = 0, int_fast64_t value = 0); - - /// Reinitialize this array accessor to point to the specified new - /// underlying memory. This does not modify the parent reference information - /// of this accessor. - void init_from_ref(ref_type) noexcept; - - /// Same as init_from_ref(ref_type) but avoid the mapping of 'ref' to memory - /// pointer. - void init_from_mem(MemRef) noexcept; - - /// Same as `init_from_ref(get_ref_from_parent())`. - void init_from_parent() noexcept; - - /// Update the parents reference to this child. This requires, of course, - /// that the parent information stored in this child is up to date. If the - /// parent pointer is set to null, this function has no effect. - void update_parent(); - - /// Called in the context of Group::commit() to ensure that attached - /// accessors stay valid across a commit. Please note that this works only - /// for non-transactional commits. Accessors obtained during a transaction - /// are always detached when the transaction ends. - /// - /// Returns true if, and only if the array has changed. If the array has not - /// changed, then its children are guaranteed to also not have changed. - bool update_from_parent(size_t old_baseline) noexcept; - - /// Change the type of an already attached array node. - /// - /// The effect of calling this function on an unattached accessor is - /// undefined. - void set_type(Type); - - /// Construct a complete copy of this array (including its subarrays) using - /// the specified target allocator and return just the reference to the - /// underlying memory. - MemRef clone_deep(Allocator& target_alloc) const; - - /// Construct an empty integer array of the specified type, and return just - /// the reference to the underlying memory. - static MemRef create_empty_array(Type, bool context_flag, Allocator&); - - /// Construct an integer array of the specified type and size, and return - /// just the reference to the underlying memory. All elements will be - /// initialized to the specified value. - static MemRef create_array(Type, bool context_flag, size_t size, int_fast64_t value, Allocator&); - - /// Construct a shallow copy of the specified slice of this array using the - /// specified target allocator. Subarrays will **not** be cloned. See - /// slice_and_clone_children() for an alternative. - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - - /// Construct a deep copy of the specified slice of this array using the - /// specified target allocator. Subarrays will be cloned. - MemRef slice_and_clone_children(size_t offset, size_t slice_size, Allocator& target_alloc) const; - - // Parent tracking - bool has_parent() const noexcept; - ArrayParent* get_parent() const noexcept; - - /// Setting a new parent affects ownership of the attached array node, if - /// any. If a non-null parent is specified, and there was no parent - /// originally, then the caller passes ownership to the parent, and vice - /// versa. This assumes, of course, that the change in parentship reflects a - /// corresponding change in the list of children in the affected parents. - void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept; - - size_t get_ndx_in_parent() const noexcept; - void set_ndx_in_parent(size_t) noexcept; - void adjust_ndx_in_parent(int diff) noexcept; - - /// Get the ref of this array as known to the parent. The caller must ensure - /// that the parent information ('pointer to parent' and 'index in parent') - /// is correct before calling this function. - ref_type get_ref_from_parent() const noexcept; - - bool is_attached() const noexcept; - - /// Detach from the underlying array node. This method has no effect if the - /// accessor is currently unattached (idempotency). - void detach() noexcept; - - size_t size() const noexcept; - bool is_empty() const noexcept; - Type get_type() const noexcept; - - static void add_to_column(IntegerColumn* column, int64_t value); - - void insert(size_t ndx, int_fast64_t value); - void add(int_fast64_t value); - - /// This function is guaranteed to not throw if the current width is - /// sufficient for the specified value (e.g. if you have called - /// ensure_minimum_width(value)) and get_alloc().is_read_only(get_ref()) - /// returns false (noexcept:array-set). Note that for a value of zero, the - /// first criterion is trivially satisfied. - void set(size_t ndx, int64_t value); - - void set_as_ref(size_t ndx, ref_type ref); - - template - void set(size_t ndx, int64_t value); - - int64_t get(size_t ndx) const noexcept; - - template - int64_t get(size_t ndx) const noexcept; - - void get_chunk(size_t ndx, int64_t res[8]) const noexcept; - - template - void get_chunk(size_t ndx, int64_t res[8]) const noexcept; - - ref_type get_as_ref(size_t ndx) const noexcept; - - RefOrTagged get_as_ref_or_tagged(size_t ndx) const noexcept; - void set(size_t ndx, RefOrTagged); - void add(RefOrTagged); - void ensure_minimum_width(RefOrTagged); - - int64_t front() const noexcept; - int64_t back() const noexcept; - - /// Remove the element at the specified index, and move elements at higher - /// indexes to the next lower index. - /// - /// This function does **not** destroy removed subarrays. That is, if the - /// erased element is a 'ref' pointing to a subarray, then that subarray - /// will not be destroyed automatically. - /// - /// This function guarantees that no exceptions will be thrown if - /// get_alloc().is_read_only(get_ref()) would return false before the - /// call. This is automatically guaranteed if the array is used in a - /// non-transactional context, or if the array has already been successfully - /// modified within the current write transaction. - void erase(size_t ndx); - - /// Same as erase(size_t), but remove all elements in the specified - /// range. - /// - /// Please note that this function does **not** destroy removed subarrays. - /// - /// This function guarantees that no exceptions will be thrown if - /// get_alloc().is_read_only(get_ref()) would return false before the call. - void erase(size_t begin, size_t end); - - /// Reduce the size of this array to the specified number of elements. It is - /// an error to specify a size that is greater than the current size of this - /// array. The effect of doing so is undefined. This is just a shorthand for - /// calling the ranged erase() function with appropriate arguments. - /// - /// Please note that this function does **not** destroy removed - /// subarrays. See clear_and_destroy_children() for an alternative. - /// - /// This function guarantees that no exceptions will be thrown if - /// get_alloc().is_read_only(get_ref()) would return false before the call. - void truncate(size_t new_size); - - /// Reduce the size of this array to the specified number of elements. It is - /// an error to specify a size that is greater than the current size of this - /// array. The effect of doing so is undefined. Subarrays will be destroyed - /// recursively, as if by a call to `destroy_deep(subarray_ref, alloc)`. - /// - /// This function is guaranteed not to throw if - /// get_alloc().is_read_only(get_ref()) returns false. - void truncate_and_destroy_children(size_t new_size); - - /// Remove every element from this array. This is just a shorthand for - /// calling truncate(0). - /// - /// Please note that this function does **not** destroy removed - /// subarrays. See clear_and_destroy_children() for an alternative. - /// - /// This function guarantees that no exceptions will be thrown if - /// get_alloc().is_read_only(get_ref()) would return false before the call. - void clear(); - - /// Remove every element in this array. Subarrays will be destroyed - /// recursively, as if by a call to `destroy_deep(subarray_ref, - /// alloc)`. This is just a shorthand for calling - /// truncate_and_destroy_children(0). - /// - /// This function guarantees that no exceptions will be thrown if - /// get_alloc().is_read_only(get_ref()) would return false before the call. - void clear_and_destroy_children(); - - /// If neccessary, expand the representation so that it can store the - /// specified value. - void ensure_minimum_width(int_fast64_t value); - - /// This one may change the represenation of the array, so be carefull if - /// you call it after ensure_minimum_width(). - void set_all_to_zero(); - - /// Add \a diff to the element at the specified index. - void adjust(size_t ndx, int_fast64_t diff); - - /// Add \a diff to all the elements in the specified index range. - void adjust(size_t begin, size_t end, int_fast64_t diff); - - /// Add signed \a diff to all elements that are greater than, or equal to \a - /// limit. - void adjust_ge(int_fast64_t limit, int_fast64_t diff); - - //@{ - /// These are similar in spirit to std::move() and std::move_backward from - /// ``. \a dest_begin must not be in the range [`begin`,`end`), and - /// \a dest_end must not be in the range (`begin`,`end`]. - /// - /// These functions are guaranteed to not throw if - /// `get_alloc().is_read_only(get_ref())` returns false. - void move(size_t begin, size_t end, size_t dest_begin); - void move_backward(size_t begin, size_t end, size_t dest_end); - //@} - - /// move_rotate moves one element from \a from to be located at index \a to, - /// shifting all elements inbetween by one. - /// - /// If \a from is larger than \a to, the elements inbetween are shifted down. - /// If \a to is larger than \a from, the elements inbetween are shifted up. - /// - /// This function is guaranteed to not throw if - /// `get_alloc().is_read_only(get_ref())` returns false. - void move_rotate(size_t from, size_t to, size_t num_elems = 1); - - //@{ - /// Find the lower/upper bound of the specified value in a sequence of - /// integers which must already be sorted ascendingly. - /// - /// For an integer value '`v`', lower_bound_int(v) returns the index '`l`' - /// of the first element such that `get(l) ≥ v`, and upper_bound_int(v) - /// returns the index '`u`' of the first element such that `get(u) > - /// v`. In both cases, if no such element is found, the returned value is - /// the number of elements in the array. - /// - /// 3 3 3 4 4 4 5 6 7 9 9 9 - /// ^ ^ ^ ^ ^ - /// | | | | | - /// | | | | -- Lower and upper bound of 15 - /// | | | | - /// | | | -- Lower and upper bound of 8 - /// | | | - /// | | -- Upper bound of 4 - /// | | - /// | -- Lower bound of 4 - /// | - /// -- Lower and upper bound of 1 - /// - /// These functions are similar to std::lower_bound() and - /// std::upper_bound(). - /// - /// We currently use binary search. See for example - /// http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary. - /// - /// FIXME: It may be worth considering if overall efficiency can be improved - /// by doing a linear search for short sequences. - size_t lower_bound_int(int64_t value) const noexcept; - size_t upper_bound_int(int64_t value) const noexcept; - //@} - - /// \brief Search the \c Array for a value greater or equal than \a target, - /// starting the search at the \a start index. If \a indirection is - /// provided, use it as a look-up table to iterate over the \c Array. - /// - /// If \a indirection is not provided, then the \c Array must be sorted in - /// ascending order. If \a indirection is provided, then its values should - /// point to indices in this \c Array in such a way that iteration happens - /// in ascending order. - /// - /// Behaviour is undefined if: - /// - a value in \a indirection is out of bounds for this \c Array; - /// - \a indirection does not contain at least as many elements as this \c - /// Array; - /// - sorting conditions are not respected; - /// - \a start is greater than the number of elements in this \c Array or - /// \a indirection (if provided). - /// - /// \param target the smallest value to search for - /// \param start the offset at which to start searching in the array - /// \param indirection an \c Array containing valid indices of values in - /// this \c Array, sorted in ascending order - /// \return the index of the value if found, or realm::not_found otherwise - size_t find_gte(const int64_t target, size_t start, size_t end = size_t(-1)) const; - - void preset(int64_t min, int64_t max, size_t num_items); - void preset(size_t bitwidth, size_t num_items); - - int64_t sum(size_t start = 0, size_t end = size_t(-1)) const; - size_t count(int64_t value) const noexcept; - - bool maximum(int64_t& result, size_t start = 0, size_t end = size_t(-1), size_t* return_ndx = nullptr) const; - - bool minimum(int64_t& result, size_t start = 0, size_t end = size_t(-1), size_t* return_ndx = nullptr) const; - - /// This information is guaranteed to be cached in the array accessor. - bool is_inner_bptree_node() const noexcept; - - /// Returns true if type is either type_HasRefs or type_InnerColumnNode. - /// - /// This information is guaranteed to be cached in the array accessor. - bool has_refs() const noexcept; - - /// This information is guaranteed to be cached in the array accessor. - /// - /// Columns and indexes can use the context bit to differentiate leaf types. - bool get_context_flag() const noexcept; - void set_context_flag(bool) noexcept; - - ref_type get_ref() const noexcept; - MemRef get_mem() const noexcept; - - /// Destroy only the array that this accessor is attached to, not the - /// children of that array. See non-static destroy_deep() for an - /// alternative. If this accessor is already in the detached state, this - /// function has no effect (idempotency). - void destroy() noexcept; - - /// Recursively destroy children (as if calling - /// clear_and_destroy_children()), then put this accessor into the detached - /// state (as if calling detach()), then free the allocated memory. If this - /// accessor is already in the detached state, this function has no effect - /// (idempotency). - void destroy_deep() noexcept; - - /// Shorthand for `destroy(MemRef(ref, alloc), alloc)`. - static void destroy(ref_type ref, Allocator& alloc) noexcept; - - /// Destroy only the specified array node, not its children. See also - /// destroy_deep(MemRef, Allocator&). - static void destroy(MemRef, Allocator&) noexcept; - - /// Shorthand for `destroy_deep(MemRef(ref, alloc), alloc)`. - static void destroy_deep(ref_type ref, Allocator& alloc) noexcept; - - /// Destroy the specified array node and all of its children, recursively. - /// - /// This is done by freeing the specified array node after calling - /// destroy_deep() for every contained 'ref' element. - static void destroy_deep(MemRef, Allocator&) noexcept; - - Allocator& get_alloc() const noexcept - { - return m_alloc; - } - - // Serialization - - /// Returns the ref (position in the target stream) of the written copy of - /// this array, or the ref of the original array if \a only_if_modified is - /// true, and this array is unmodified (Alloc::is_read_only()). - /// - /// The number of bytes that will be written by a non-recursive invocation - /// of this function is exactly the number returned by get_byte_size(). - /// - /// \param out The destination stream (writer). - /// - /// \param deep If true, recursively write out subarrays, but still subject - /// to \a only_if_modified. - /// - /// \param only_if_modified Set to `false` to always write, or to `true` to - /// only write the array if it has been modified. - ref_type write(_impl::ArrayWriterBase& out, bool deep, bool only_if_modified) const; - - /// Same as non-static write() with `deep` set to true. This is for the - /// cases where you do not already have an array accessor available. - static ref_type write(ref_type, Allocator&, _impl::ArrayWriterBase&, bool only_if_modified); - - // Main finding function - used for find_first, find_all, sum, max, min, etc. - bool find(int cond, Action action, int64_t value, size_t start, size_t end, size_t baseindex, - QueryState* state, bool nullable_array = false, bool find_null = false) const; - - // Templated find function to avoid conversion to and from integer represenation of condition - template - bool find(Action action, int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - bool nullable_array = false, bool find_null = false) const - { - if (action == act_ReturnFirst) { - REALM_TEMPEX3(return find, cond, act_ReturnFirst, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_Sum) { - REALM_TEMPEX3(return find, cond, act_Sum, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_Min) { - REALM_TEMPEX3(return find, cond, act_Min, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_Max) { - REALM_TEMPEX3(return find, cond, act_Max, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_Count) { - REALM_TEMPEX3(return find, cond, act_Count, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_FindAll) { - REALM_TEMPEX3(return find, cond, act_FindAll, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - else if (action == act_CallbackIdx) { - REALM_TEMPEX3(return find, cond, act_CallbackIdx, m_width, - (value, start, end, baseindex, state, CallbackDummy(), nullable_array, find_null)) - } - REALM_ASSERT_DEBUG(false); - return false; - } - - - /* - bool find(int cond, Action action, null, size_t start, size_t end, size_t baseindex, - QueryState* state) const; - */ - - template - bool find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array = false, bool find_null = false) const; - - // This is the one installed into the m_vtable->finder slots. - template - bool find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state) const; - - template - bool find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array = false, bool find_null = false) const; - - /* - template - bool find(null, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const; - */ - - // Optimized implementation for release mode - template - bool find_optimized(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array = false, bool find_null = false) const; - - // Called for each search result - template - bool find_action(size_t index, util::Optional value, QueryState* state, - Callback callback) const; - - template - bool find_action_pattern(size_t index, uint64_t pattern, QueryState* state, Callback callback) const; - - // Wrappers for backwards compatibility and for simple use without - // setting up state initialization etc - template - size_t find_first(int64_t value, size_t start = 0, size_t end = size_t(-1)) const; - - void find_all(IntegerColumn* result, int64_t value, size_t col_offset = 0, size_t begin = 0, - size_t end = size_t(-1)) const; - - size_t find_first(int64_t value, size_t begin = 0, size_t end = size_t(-1)) const; - - // Non-SSE find for the four functions Equal/NotEqual/Less/Greater - template - bool compare(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - // Non-SSE find for Equal/NotEqual - template - inline bool compare_equality(int64_t value, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const; - - // Non-SSE find for Less/Greater - template - bool compare_relation(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - template - bool compare_leafs_4(const Array* foreign, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - template - bool compare_leafs(const Array* foreign, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - template - bool compare_leafs(const Array* foreign, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - template - bool compare_leafs(const Array* foreign, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - -// SSE find for the four functions Equal/NotEqual/Less/Greater -#ifdef REALM_COMPILER_SSE - template - bool find_sse(int64_t value, __m128i* data, size_t items, QueryState* state, size_t baseindex, - Callback callback) const; - - template - REALM_FORCEINLINE bool find_sse_intern(__m128i* action_data, __m128i* data, size_t items, - QueryState* state, size_t baseindex, Callback callback) const; - -#endif - - template - inline bool test_zero(uint64_t value) const; // Tests value for 0-elements - - template - size_t find_zero(uint64_t v) const; // Finds position of 0/non-zero element - - template - uint64_t cascade(uint64_t a) const; // Sets lowermost bits of zero or non-zero elements - - template - int64_t - find_gtlt_magic(int64_t v) const; // Compute magic constant needed for searching for value 'v' using bit hacks - - template - inline int64_t lower_bits() const; // Return chunk with lower bit set in each element - - size_t first_set_bit(unsigned int v) const; - size_t first_set_bit64(int64_t v) const; - - template - int64_t get_universal(const char* const data, const size_t ndx) const; - - // Find value greater/less in 64-bit chunk - only works for positive values - template - bool find_gtlt_fast(uint64_t chunk, uint64_t magic, QueryState* state, size_t baseindex, - Callback callback) const; - - // Find value greater/less in 64-bit chunk - no constraints - template - bool find_gtlt(int64_t v, uint64_t chunk, QueryState* state, size_t baseindex, Callback callback) const; - - ref_type bptree_leaf_insert(size_t ndx, int64_t, TreeInsertBase& state); - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static int_fast64_t get(const char* header, size_t ndx) noexcept; - - /// Like get(const char*, size_t) but gets two consecutive - /// elements. - static std::pair get_two(const char* header, size_t ndx) noexcept; - - static void get_three(const char* data, size_t ndx, ref_type& v0, ref_type& v1, ref_type& v2) noexcept; - - /// The meaning of 'width' depends on the context in which this - /// array is used. - size_t get_width() const noexcept - { - return m_width; - } - - static char* get_data_from_header(char*) noexcept; - static char* get_header_from_data(char*) noexcept; - static const char* get_data_from_header(const char*) noexcept; - - enum WidthType { - wtype_Bits = 0, - wtype_Multiply = 1, - wtype_Ignore = 2, - }; - - static bool get_is_inner_bptree_node_from_header(const char*) noexcept; - static bool get_hasrefs_from_header(const char*) noexcept; - static bool get_context_flag_from_header(const char*) noexcept; - static WidthType get_wtype_from_header(const char*) noexcept; - static uint_least8_t get_width_from_header(const char*) noexcept; - static size_t get_size_from_header(const char*) noexcept; - - static Type get_type_from_header(const char*) noexcept; - - /// Get the number of bytes currently in use by this array. This - /// includes the array header, but it does not include allocated - /// bytes corresponding to excess capacity. The result is - /// guaranteed to be a multiple of 8 (i.e., 64-bit aligned). - /// - /// This number is exactly the number of bytes that will be - /// written by a non-recursive invocation of write(). - size_t get_byte_size() const noexcept; - - /// Get the maximum number of bytes that can be written by a - /// non-recursive invocation of write() on an array with the - /// specified number of elements, that is, the maximum value that - /// can be returned by get_byte_size(). - static size_t get_max_byte_size(size_t num_elems) noexcept; - - /// FIXME: Belongs in IntegerArray - static size_t calc_aligned_byte_size(size_t size, int width); - -#ifdef REALM_DEBUG - void print() const; - void verify() const; - typedef size_t (*LeafVerifier)(MemRef, Allocator&); - void verify_bptree(LeafVerifier) const; - class MemUsageHandler { - public: - virtual void handle(ref_type ref, size_t allocated, size_t used) = 0; - }; - void report_memory_usage(MemUsageHandler&) const; - void stats(MemStats& stats_dest) const; - typedef void (*LeafDumper)(MemRef, Allocator&, std::ostream&, int level); - void dump_bptree_structure(std::ostream&, int level, LeafDumper) const; - void to_dot(std::ostream&, StringData title = StringData()) const; - class ToDotHandler { - public: - virtual void to_dot(MemRef leaf_mem, ArrayParent*, size_t ndx_in_parent, std::ostream&) = 0; - ~ToDotHandler() - { - } - }; - void bptree_to_dot(std::ostream&, ToDotHandler&) const; - void to_dot_parent_edge(std::ostream&) const; -#endif - - static const int header_size = 8; // Number of bytes used by header - - // The encryption layer relies on headers always fitting within a single page. - static_assert(header_size == 8, "Header must always fit in entirely on a page"); - -private: - Array& operator=(const Array&); // not allowed -protected: - typedef bool (*CallbackDummy)(int64_t); - -protected: - // Includes array header. Not necessarily 8-byte aligned. - virtual size_t calc_byte_len(size_t num_items, size_t width) const; - - virtual size_t calc_item_count(size_t bytes, size_t width) const noexcept; - - bool get_is_inner_bptree_node_from_header() const noexcept; - bool get_hasrefs_from_header() const noexcept; - bool get_context_flag_from_header() const noexcept; - WidthType get_wtype_from_header() const noexcept; - uint_least8_t get_width_from_header() const noexcept; - size_t get_size_from_header() const noexcept; - - // Undefined behavior if m_alloc.is_read_only(m_ref) returns true - size_t get_capacity_from_header() const noexcept; - - void set_header_is_inner_bptree_node(bool value) noexcept; - void set_header_hasrefs(bool value) noexcept; - void set_header_context_flag(bool value) noexcept; - void set_header_wtype(WidthType value) noexcept; - void set_header_width(int value) noexcept; - void set_header_size(size_t value) noexcept; - void set_header_capacity(size_t value) noexcept; - - static void set_header_is_inner_bptree_node(bool value, char* header) noexcept; - static void set_header_hasrefs(bool value, char* header) noexcept; - static void set_header_context_flag(bool value, char* header) noexcept; - static void set_header_wtype(WidthType value, char* header) noexcept; - static void set_header_width(int value, char* header) noexcept; - static void set_header_size(size_t value, char* header) noexcept; - static void set_header_capacity(size_t value, char* header) noexcept; - - static void init_header(char* header, bool is_inner_bptree_node, bool has_refs, bool context_flag, - WidthType width_type, int width, size_t size, size_t capacity) noexcept; - - - // This returns the minimum value ("lower bound") of the representable values - // for the given bit width. Valid widths are 0, 1, 2, 4, 8, 16, 32, and 64. - template - static int_fast64_t lbound_for_width() noexcept; - - static int_fast64_t lbound_for_width(size_t width) noexcept; - - // This returns the maximum value ("inclusive upper bound") of the representable values - // for the given bit width. Valid widths are 0, 1, 2, 4, 8, 16, 32, and 64. - template - static int_fast64_t ubound_for_width() noexcept; - - static int_fast64_t ubound_for_width(size_t width) noexcept; - - template - void set_width() noexcept; - void set_width(size_t) noexcept; - void alloc(size_t init_size, size_t width); - void copy_on_write(); - -private: - template - int64_t sum(size_t start, size_t end) const; - - template - bool minmax(int64_t& result, size_t start, size_t end, size_t* return_ndx) const; - - template - size_t find_gte(const int64_t target, size_t start, size_t end) const; - - template - size_t adjust_ge(size_t start, size_t end, int_fast64_t limit, int_fast64_t diff); - -protected: - /// The total size in bytes (including the header) of a new empty - /// array. Must be a multiple of 8 (i.e., 64-bit aligned). - static const size_t initial_capacity = 128; - - /// It is an error to specify a non-zero value unless the width - /// type is wtype_Bits. It is also an error to specify a non-zero - /// size if the width type is wtype_Ignore. - static MemRef create(Type, bool context_flag, WidthType, size_t size, int_fast64_t value, Allocator&); - - static MemRef clone(MemRef header, Allocator& alloc, Allocator& target_alloc); - - /// Get the address of the header of this array. - char* get_header() noexcept; - - /// Same as get_byte_size(). - static size_t get_byte_size_from_header(const char*) noexcept; - - // Undefined behavior if array is in immutable memory - static size_t get_capacity_from_header(const char*) noexcept; - - // Overriding method in ArrayParent - void update_child_ref(size_t, ref_type) override; - - // Overriding method in ArrayParent - ref_type get_child_ref(size_t) const noexcept override; - - void destroy_children(size_t offset = 0) noexcept; - - std::pair get_to_dot_parent(size_t ndx_in_parent) const override; - -protected: - // Getters and Setters for adaptive-packed arrays - typedef int64_t (Array::*Getter)(size_t) const; // Note: getters must not throw - typedef void (Array::*Setter)(size_t, int64_t); - typedef bool (Array::*Finder)(int64_t, size_t, size_t, size_t, QueryState*) const; - typedef void (Array::*ChunkGetter)(size_t, int64_t res[8]) const; // Note: getters must not throw - - struct VTable { - Getter getter; - ChunkGetter chunk_getter; - Setter setter; - Finder finder[cond_VTABLE_FINDER_COUNT]; // one for each active function pointer - }; - template - struct VTableForWidth; - -protected: - /// Takes a 64-bit value and returns the minimum number of bits needed - /// to fit the value. For alignment this is rounded up to nearest - /// log2. Posssible results {0, 1, 2, 4, 8, 16, 32, 64} - static size_t bit_width(int64_t value); - -#ifdef REALM_DEBUG - void report_memory_usage_2(MemUsageHandler&) const; -#endif - -private: - Getter m_getter = nullptr; // cached to avoid indirection - const VTable* m_vtable = nullptr; - -public: - // FIXME: Should not be public - char* m_data = nullptr; // Points to first byte after header - -#if REALM_ENABLE_MEMDEBUG - // If m_no_relocation is false, then copy_on_write() will always relocate this array, regardless if it's - // required or not. If it's true, then it will never relocate, which is currently only expeted inside - // GroupWriter::write_group() due to a unique chicken/egg problem (see description there). - bool m_no_relocation = false; -#endif - -protected: - int64_t m_lbound; // min number that can be stored with current m_width - int64_t m_ubound; // max number that can be stored with current m_width - - size_t m_size = 0; // Number of elements currently stored. - size_t m_capacity = 0; // Number of elements that fit inside the allocated memory. - - Allocator& m_alloc; - -private: - size_t m_ref; - ArrayParent* m_parent = nullptr; - size_t m_ndx_in_parent = 0; // Ignored if m_parent is null. - -protected: - uint_least8_t m_width = 0; // Size of an element (meaning depend on type of array). - bool m_is_inner_bptree_node; // This array is an inner node of B+-tree. - bool m_has_refs; // Elements whose first bit is zero are refs to subarrays. - bool m_context_flag; // Meaning depends on context. - -private: - ref_type do_write_shallow(_impl::ArrayWriterBase&) const; - ref_type do_write_deep(_impl::ArrayWriterBase&, bool only_if_modified) const; - static size_t calc_byte_size(WidthType wtype, size_t size, uint_least8_t width) noexcept; - - friend class SlabAlloc; - friend class GroupWriter; - friend class StringColumn; -}; - - - - -// Implementation: - -class QueryStateBase { - virtual void dyncast() - { - } -}; - -template <> -class QueryState : public QueryStateBase { -public: - int64_t m_state; - size_t m_match_count; - size_t m_limit; - size_t m_minmax_index; // used only for min/max, to save index of current min/max value - - template - bool uses_val() - { - if (action == act_Max || action == act_Min || action == act_Sum) - return true; - else - return false; - } - - void init(Action action, IntegerColumn* akku, size_t limit) - { - m_match_count = 0; - m_limit = limit; - m_minmax_index = not_found; - - if (action == act_Max) - m_state = -0x7fffffffffffffffLL - 1LL; - else if (action == act_Min) - m_state = 0x7fffffffffffffffLL; - else if (action == act_ReturnFirst) - m_state = not_found; - else if (action == act_Sum) - m_state = 0; - else if (action == act_Count) - m_state = 0; - else if (action == act_FindAll) - m_state = reinterpret_cast(akku); - else if (action == act_CallbackIdx) { - } - else { - REALM_ASSERT_DEBUG(false); - } - } - - template - inline bool match(size_t index, uint64_t indexpattern, int64_t value) - { - if (pattern) { - if (action == act_Count) { - // If we are close to 'limit' argument in query, we cannot count-up a complete chunk. Count up single - // elements instead - if (m_match_count + 64 >= m_limit) - return false; - - m_state += fast_popcount64(indexpattern); - m_match_count = size_t(m_state); - return true; - } - // Other aggregates cannot (yet) use bit pattern for anything. Make Array-finder call with pattern = false - // instead - return false; - } - - ++m_match_count; - - if (action == act_Max) { - if (value > m_state) { - m_state = value; - m_minmax_index = index; - } - } - else if (action == act_Min) { - if (value < m_state) { - m_state = value; - m_minmax_index = index; - } - } - else if (action == act_Sum) - m_state += value; - else if (action == act_Count) { - m_state++; - m_match_count = size_t(m_state); - } - else if (action == act_FindAll) { - Array::add_to_column(reinterpret_cast(m_state), index); - } - else if (action == act_ReturnFirst) { - m_state = index; - return false; - } - else { - REALM_ASSERT_DEBUG(false); - } - return (m_limit > m_match_count); - } - - template - inline bool match(size_t index, uint64_t indexpattern, util::Optional value) - { - // FIXME: This is a temporary hack for nullable integers. - if (value) { - return match(index, indexpattern, *value); - } - - // If value is null, the only sensible actions are count, find_all, and return first. - // Max, min, and sum should all have no effect. - if (action == act_Count) { - m_state++; - m_match_count = size_t(m_state); - } - else if (action == act_FindAll) { - Array::add_to_column(reinterpret_cast(m_state), index); - } - else if (action == act_ReturnFirst) { - m_match_count++; - m_state = index; - return false; - } - return m_limit > m_match_count; - } -}; - -// Used only for Basic-types: currently float and double -template -class QueryState : public QueryStateBase { -public: - R m_state; - size_t m_match_count; - size_t m_limit; - size_t m_minmax_index; // used only for min/max, to save index of current min/max value - - template - bool uses_val() - { - return (action == act_Max || action == act_Min || action == act_Sum || action == act_Count); - } - - void init(Action action, Array*, size_t limit) - { - REALM_ASSERT((std::is_same::value || std::is_same::value)); - m_match_count = 0; - m_limit = limit; - m_minmax_index = not_found; - - if (action == act_Max) - m_state = -std::numeric_limits::infinity(); - else if (action == act_Min) - m_state = std::numeric_limits::infinity(); - else if (action == act_Sum) - m_state = 0.0; - else { - REALM_ASSERT_DEBUG(false); - } - } - - template - inline bool match(size_t index, uint64_t /*indexpattern*/, resulttype value) - { - if (pattern) - return false; - - static_assert(action == act_Sum || action == act_Max || action == act_Min || action == act_Count, - "Search action not supported"); - - if (action == act_Count) { - ++m_match_count; - } - else if (!null::is_null_float(value)) { - ++m_match_count; - if (action == act_Max) { - if (value > m_state) { - m_state = value; - m_minmax_index = index; - } - } - else if (action == act_Min) { - if (value < m_state) { - m_state = value; - m_minmax_index = index; - } - } - else if (action == act_Sum) - m_state += value; - else { - REALM_ASSERT_DEBUG(false); - } - } - - return (m_limit > m_match_count); - } -}; - -inline bool RefOrTagged::is_ref() const noexcept -{ - return (m_value & 1) == 0; -} - -inline bool RefOrTagged::is_tagged() const noexcept -{ - return !is_ref(); -} - -inline ref_type RefOrTagged::get_as_ref() const noexcept -{ - // to_ref() is defined in - return to_ref(m_value); -} - -inline uint_fast64_t RefOrTagged::get_as_int() const noexcept -{ - // The bitwise AND is there in case uint_fast64_t is wider than 64 bits. - return (uint_fast64_t(m_value) & 0xFFFFFFFFFFFFFFFFULL) >> 1; -} - -inline RefOrTagged RefOrTagged::make_ref(ref_type ref) noexcept -{ - // from_ref() is defined in - int_fast64_t value = from_ref(ref); - return RefOrTagged(value); -} - -inline RefOrTagged RefOrTagged::make_tagged(uint_fast64_t i) noexcept -{ - REALM_ASSERT(i < (1ULL << 63)); - int_fast64_t value = util::from_twos_compl((i << 1) | 1); - return RefOrTagged(value); -} - -inline RefOrTagged::RefOrTagged(int_fast64_t value) noexcept - : m_value(value) -{ -} - -inline Array::Array(Allocator& allocator) noexcept - : m_alloc(allocator) -{ -} - -inline void Array::create(Type type, bool context_flag, size_t length, int_fast64_t value) -{ - MemRef mem = create_array(type, context_flag, length, value, m_alloc); // Throws - init_from_mem(mem); -} - - -inline void Array::init_from_ref(ref_type ref) noexcept -{ - REALM_ASSERT_DEBUG(ref); - char* header = m_alloc.translate(ref); - init_from_mem(MemRef(header, ref, m_alloc)); -} - - -inline void Array::init_from_parent() noexcept -{ - ref_type ref = get_ref_from_parent(); - init_from_ref(ref); -} - - -inline Array::Type Array::get_type() const noexcept -{ - if (m_is_inner_bptree_node) { - REALM_ASSERT_DEBUG(m_has_refs); - return type_InnerBptreeNode; - } - if (m_has_refs) - return type_HasRefs; - return type_Normal; -} - - -inline void Array::get_chunk(size_t ndx, int64_t res[8]) const noexcept -{ - REALM_ASSERT_DEBUG(ndx < m_size); - (this->*(m_vtable->chunk_getter))(ndx, res); -} - - -inline int64_t Array::get(size_t ndx) const noexcept -{ - REALM_ASSERT_DEBUG(is_attached()); - REALM_ASSERT_DEBUG(ndx < m_size); - return (this->*m_getter)(ndx); - - // Two ideas that are not efficient but may be worth looking into again: - /* - // Assume correct width is found early in REALM_TEMPEX, which is the case for B tree offsets that - // are probably either 2^16 long. Turns out to be 25% faster if found immediately, but 50-300% slower - // if found later - REALM_TEMPEX(return get, (ndx)); - */ - /* - // Slightly slower in both of the if-cases. Also needs an matchcount m_size check too, to avoid - // reading beyond array. - if (m_width >= 8 && m_size > ndx + 7) - return get<64>(ndx >> m_shift) & m_widthmask; - else - return (this->*(m_vtable->getter))(ndx); - */ -} - -inline int64_t Array::front() const noexcept -{ - return get(0); -} - -inline int64_t Array::back() const noexcept -{ - return get(m_size - 1); -} - -inline ref_type Array::get_as_ref(size_t ndx) const noexcept -{ - REALM_ASSERT_DEBUG(is_attached()); - REALM_ASSERT_DEBUG(m_has_refs); - int64_t v = get(ndx); - return to_ref(v); -} - -inline RefOrTagged Array::get_as_ref_or_tagged(size_t ndx) const noexcept -{ - REALM_ASSERT(has_refs()); - return RefOrTagged(get(ndx)); -} - -inline void Array::set(size_t ndx, RefOrTagged ref_or_tagged) -{ - REALM_ASSERT(has_refs()); - set(ndx, ref_or_tagged.m_value); // Throws -} - -inline void Array::add(RefOrTagged ref_or_tagged) -{ - REALM_ASSERT(has_refs()); - add(ref_or_tagged.m_value); // Throws -} - -inline void Array::ensure_minimum_width(RefOrTagged ref_or_tagged) -{ - REALM_ASSERT(has_refs()); - ensure_minimum_width(ref_or_tagged.m_value); // Throws -} - -inline bool Array::is_inner_bptree_node() const noexcept -{ - return m_is_inner_bptree_node; -} - -inline bool Array::has_refs() const noexcept -{ - return m_has_refs; -} - -inline bool Array::get_context_flag() const noexcept -{ - return m_context_flag; -} - -inline void Array::set_context_flag(bool value) noexcept -{ - m_context_flag = value; - set_header_context_flag(value); -} - -inline ref_type Array::get_ref() const noexcept -{ - return m_ref; -} - -inline MemRef Array::get_mem() const noexcept -{ - return MemRef(get_header_from_data(m_data), m_ref, m_alloc); -} - -inline void Array::destroy() noexcept -{ - if (!is_attached()) - return; - char* header = get_header_from_data(m_data); - m_alloc.free_(m_ref, header); - m_data = nullptr; -} - -inline void Array::destroy_deep() noexcept -{ - if (!is_attached()) - return; - - if (m_has_refs) - destroy_children(); - - char* header = get_header_from_data(m_data); - m_alloc.free_(m_ref, header); - m_data = nullptr; -} - -inline ref_type Array::write(_impl::ArrayWriterBase& out, bool deep, bool only_if_modified) const -{ - REALM_ASSERT(is_attached()); - - if (only_if_modified && m_alloc.is_read_only(m_ref)) - return m_ref; - - if (!deep || !m_has_refs) - return do_write_shallow(out); // Throws - - return do_write_deep(out, only_if_modified); // Throws -} - -inline ref_type Array::write(ref_type ref, Allocator& alloc, _impl::ArrayWriterBase& out, bool only_if_modified) -{ - if (only_if_modified && alloc.is_read_only(ref)) - return ref; - - Array array(alloc); - array.init_from_ref(ref); - - if (!array.m_has_refs) - return array.do_write_shallow(out); // Throws - - return array.do_write_deep(out, only_if_modified); // Throws -} - -inline void Array::add(int_fast64_t value) -{ - insert(m_size, value); -} - -inline void Array::erase(size_t ndx) -{ - // This can throw, but only if array is currently in read-only - // memory. - move(ndx + 1, size(), ndx); - - // Update size (also in header) - --m_size; - set_header_size(m_size); -} - - -inline void Array::erase(size_t begin, size_t end) -{ - if (begin != end) { - // This can throw, but only if array is currently in read-only memory. - move(end, size(), begin); // Throws - - // Update size (also in header) - m_size -= end - begin; - set_header_size(m_size); - } -} - -inline void Array::clear() -{ - truncate(0); // Throws -} - -inline void Array::clear_and_destroy_children() -{ - truncate_and_destroy_children(0); -} - -inline void Array::destroy(ref_type ref, Allocator& alloc) noexcept -{ - destroy(MemRef(ref, alloc), alloc); -} - -inline void Array::destroy(MemRef mem, Allocator& alloc) noexcept -{ - alloc.free_(mem); -} - -inline void Array::destroy_deep(ref_type ref, Allocator& alloc) noexcept -{ - destroy_deep(MemRef(ref, alloc), alloc); -} - -inline void Array::destroy_deep(MemRef mem, Allocator& alloc) noexcept -{ - if (!get_hasrefs_from_header(mem.get_addr())) { - alloc.free_(mem); - return; - } - Array array(alloc); - array.init_from_mem(mem); - array.destroy_deep(); -} - - -inline void Array::adjust(size_t ndx, int_fast64_t diff) -{ - REALM_ASSERT_3(ndx, <=, m_size); - if (diff != 0) { - // FIXME: Should be optimized - int_fast64_t v = get(ndx); - set(ndx, int64_t(v + diff)); // Throws - } -} - -inline void Array::adjust(size_t begin, size_t end, int_fast64_t diff) -{ - if (diff != 0) { - // FIXME: Should be optimized - for (size_t i = begin; i != end; ++i) - adjust(i, diff); // Throws - } -} - - -//------------------------------------------------- - -inline bool Array::get_is_inner_bptree_node_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return (int(h[4]) & 0x80) != 0; -} -inline bool Array::get_hasrefs_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return (int(h[4]) & 0x40) != 0; -} -inline bool Array::get_context_flag_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return (int(h[4]) & 0x20) != 0; -} -inline Array::WidthType Array::get_wtype_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return WidthType((int(h[4]) & 0x18) >> 3); -} -inline uint_least8_t Array::get_width_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return uint_least8_t((1 << (int(h[4]) & 0x07)) >> 1); -} -inline size_t Array::get_size_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return (size_t(h[5]) << 16) + (size_t(h[6]) << 8) + h[7]; -} -inline size_t Array::get_capacity_from_header(const char* header) noexcept -{ - typedef unsigned char uchar; - const uchar* h = reinterpret_cast(header); - return (size_t(h[0]) << 16) + (size_t(h[1]) << 8) + h[2]; -} - - -inline char* Array::get_data_from_header(char* header) noexcept -{ - return header + header_size; -} -inline char* Array::get_header_from_data(char* data) noexcept -{ - return data - header_size; -} -inline const char* Array::get_data_from_header(const char* header) noexcept -{ - return get_data_from_header(const_cast(header)); -} - - -inline bool Array::get_is_inner_bptree_node_from_header() const noexcept -{ - return get_is_inner_bptree_node_from_header(get_header_from_data(m_data)); -} -inline bool Array::get_hasrefs_from_header() const noexcept -{ - return get_hasrefs_from_header(get_header_from_data(m_data)); -} -inline bool Array::get_context_flag_from_header() const noexcept -{ - return get_context_flag_from_header(get_header_from_data(m_data)); -} -inline Array::WidthType Array::get_wtype_from_header() const noexcept -{ - return get_wtype_from_header(get_header_from_data(m_data)); -} -inline uint_least8_t Array::get_width_from_header() const noexcept -{ - return get_width_from_header(get_header_from_data(m_data)); -} -inline size_t Array::get_size_from_header() const noexcept -{ - return get_size_from_header(get_header_from_data(m_data)); -} -inline size_t Array::get_capacity_from_header() const noexcept -{ - return get_capacity_from_header(get_header_from_data(m_data)); -} - - -inline void Array::set_header_is_inner_bptree_node(bool value, char* header) noexcept -{ - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[4] = uchar((int(h[4]) & ~0x80) | int(value) << 7); -} - -inline void Array::set_header_hasrefs(bool value, char* header) noexcept -{ - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[4] = uchar((int(h[4]) & ~0x40) | int(value) << 6); -} - -inline void Array::set_header_context_flag(bool value, char* header) noexcept -{ - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[4] = uchar((int(h[4]) & ~0x20) | int(value) << 5); -} - -inline void Array::set_header_wtype(WidthType value, char* header) noexcept -{ - // Indicates how to calculate size in bytes based on width - // 0: bits (width/8) * size - // 1: multiply width * size - // 2: ignore 1 * size - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[4] = uchar((int(h[4]) & ~0x18) | int(value) << 3); -} - -inline void Array::set_header_width(int value, char* header) noexcept -{ - // Pack width in 3 bits (log2) - int w = 0; - while (value) { - ++w; - value >>= 1; - } - REALM_ASSERT_3(w, <, 8); - - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[4] = uchar((int(h[4]) & ~0x7) | w); -} - -inline void Array::set_header_size(size_t value, char* header) noexcept -{ - REALM_ASSERT_3(value, <=, max_array_payload); - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[5] = uchar((value >> 16) & 0x000000FF); - h[6] = uchar((value >> 8) & 0x000000FF); - h[7] = uchar(value & 0x000000FF); -} - -// Note: There is a copy of this function is test_alloc.cpp -inline void Array::set_header_capacity(size_t value, char* header) noexcept -{ - REALM_ASSERT_3(value, <=, max_array_payload); - typedef unsigned char uchar; - uchar* h = reinterpret_cast(header); - h[0] = uchar((value >> 16) & 0x000000FF); - h[1] = uchar((value >> 8) & 0x000000FF); - h[2] = uchar(value & 0x000000FF); -} - - -inline void Array::set_header_is_inner_bptree_node(bool value) noexcept -{ - set_header_is_inner_bptree_node(value, get_header_from_data(m_data)); -} -inline void Array::set_header_hasrefs(bool value) noexcept -{ - set_header_hasrefs(value, get_header_from_data(m_data)); -} -inline void Array::set_header_context_flag(bool value) noexcept -{ - set_header_context_flag(value, get_header_from_data(m_data)); -} -inline void Array::set_header_wtype(WidthType value) noexcept -{ - set_header_wtype(value, get_header_from_data(m_data)); -} -inline void Array::set_header_width(int value) noexcept -{ - set_header_width(value, get_header_from_data(m_data)); -} -inline void Array::set_header_size(size_t value) noexcept -{ - set_header_size(value, get_header_from_data(m_data)); -} -inline void Array::set_header_capacity(size_t value) noexcept -{ - set_header_capacity(value, get_header_from_data(m_data)); -} - - -inline Array::Type Array::get_type_from_header(const char* header) noexcept -{ - if (get_is_inner_bptree_node_from_header(header)) - return type_InnerBptreeNode; - if (get_hasrefs_from_header(header)) - return type_HasRefs; - return type_Normal; -} - - -inline char* Array::get_header() noexcept -{ - return get_header_from_data(m_data); -} - -inline size_t Array::calc_byte_size(WidthType wtype, size_t size, uint_least8_t width) noexcept -{ - size_t num_bytes = 0; - switch (wtype) { - case wtype_Bits: { - // Current assumption is that size is at most 2^24 and that width is at most 64. - // In that case the following will never overflow. (Assuming that size_t is at least 32 bits) - REALM_ASSERT_3(size, <, 0x1000000); - size_t num_bits = size * width; - num_bytes = (num_bits + 7) >> 3; - break; - } - case wtype_Multiply: { - num_bytes = size * width; - break; - } - case wtype_Ignore: - num_bytes = size; - break; - } - - // Ensure 8-byte alignment - num_bytes = (num_bytes + 7) & ~size_t(7); - - num_bytes += header_size; - - return num_bytes; -} - -inline size_t Array::get_byte_size() const noexcept -{ - const char* header = get_header_from_data(m_data); - WidthType wtype = get_wtype_from_header(header); - size_t num_bytes = calc_byte_size(wtype, m_size, m_width); - - REALM_ASSERT_7(m_alloc.is_read_only(m_ref), ==, true, ||, num_bytes, <=, get_capacity_from_header(header)); - - return num_bytes; -} - - -inline size_t Array::get_byte_size_from_header(const char* header) noexcept -{ - size_t size = get_size_from_header(header); - uint_least8_t width = get_width_from_header(header); - WidthType wtype = get_wtype_from_header(header); - size_t num_bytes = calc_byte_size(wtype, size, width); - - return num_bytes; -} - - -inline void Array::init_header(char* header, bool is_inner_bptree_node, bool has_refs, bool context_flag, - WidthType width_type, int width, size_t size, size_t capacity) noexcept -{ - // Note: Since the header layout contains unallocated bit and/or - // bytes, it is important that we put the entire header into a - // well defined state initially. - std::fill(header, header + header_size, 0); - set_header_is_inner_bptree_node(is_inner_bptree_node, header); - set_header_hasrefs(has_refs, header); - set_header_context_flag(context_flag, header); - set_header_wtype(width_type, header); - set_header_width(width, header); - set_header_size(size, header); - set_header_capacity(capacity, header); -} - - -//------------------------------------------------- - -inline MemRef Array::clone_deep(Allocator& target_alloc) const -{ - char* header = get_header_from_data(m_data); - return clone(MemRef(header, m_ref, m_alloc), m_alloc, target_alloc); // Throws -} - -inline MemRef Array::create_empty_array(Type type, bool context_flag, Allocator& alloc) -{ - size_t size = 0; - int_fast64_t value = 0; - return create_array(type, context_flag, size, value, alloc); // Throws -} - -inline MemRef Array::create_array(Type type, bool context_flag, size_t size, int_fast64_t value, Allocator& alloc) -{ - return create(type, context_flag, wtype_Bits, size, value, alloc); // Throws -} - -inline bool Array::has_parent() const noexcept -{ - return m_parent != nullptr; -} - -inline ArrayParent* Array::get_parent() const noexcept -{ - return m_parent; -} - -inline void Array::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept -{ - m_parent = parent; - m_ndx_in_parent = ndx_in_parent; -} - -inline size_t Array::get_ndx_in_parent() const noexcept -{ - return m_ndx_in_parent; -} - -inline void Array::set_ndx_in_parent(size_t ndx) noexcept -{ - m_ndx_in_parent = ndx; -} - -inline void Array::adjust_ndx_in_parent(int diff) noexcept -{ - // Note that `diff` is promoted to an unsigned type, and that - // C++03 still guarantees the expected result regardless of the - // sizes of `int` and `decltype(m_ndx_in_parent)`. - m_ndx_in_parent += diff; -} - -inline ref_type Array::get_ref_from_parent() const noexcept -{ - ref_type ref = m_parent->get_child_ref(m_ndx_in_parent); - return ref; -} - -inline bool Array::is_attached() const noexcept -{ - return m_data != nullptr; -} - -inline void Array::detach() noexcept -{ - m_data = nullptr; -} - -inline size_t Array::size() const noexcept -{ - REALM_ASSERT_DEBUG(is_attached()); - return m_size; -} - -inline bool Array::is_empty() const noexcept -{ - return size() == 0; -} - -inline size_t Array::get_max_byte_size(size_t num_elems) noexcept -{ - int max_bytes_per_elem = 8; - return header_size + num_elems * max_bytes_per_elem; -} - -inline void Array::update_parent() -{ - if (m_parent) - m_parent->update_child_ref(m_ndx_in_parent, m_ref); -} - - -inline void Array::update_child_ref(size_t child_ndx, ref_type new_ref) -{ - set(child_ndx, new_ref); -} - -inline ref_type Array::get_child_ref(size_t child_ndx) const noexcept -{ - return get_as_ref(child_ndx); -} - - -//************************************************************************************* -// Finding code * -//************************************************************************************* - -template -int64_t Array::get(size_t ndx) const noexcept -{ - return get_universal(m_data, ndx); -} - -template -int64_t Array::get_universal(const char* data, size_t ndx) const -{ - if (w == 0) { - return 0; - } - else if (w == 1) { - size_t offset = ndx >> 3; - return (data[offset] >> (ndx & 7)) & 0x01; - } - else if (w == 2) { - size_t offset = ndx >> 2; - return (data[offset] >> ((ndx & 3) << 1)) & 0x03; - } - else if (w == 4) { - size_t offset = ndx >> 1; - return (data[offset] >> ((ndx & 1) << 2)) & 0x0F; - } - else if (w == 8) { - return *reinterpret_cast(data + ndx); - } - else if (w == 16) { - size_t offset = ndx * 2; - return *reinterpret_cast(data + offset); - } - else if (w == 32) { - size_t offset = ndx * 4; - return *reinterpret_cast(data + offset); - } - else if (w == 64) { - size_t offset = ndx * 8; - return *reinterpret_cast(data + offset); - } - else { - REALM_ASSERT_DEBUG(false); - return int64_t(-1); - } -} - -/* -find() (calls find_optimized()) will call match() for each search result. - -If pattern == true: - 'indexpattern' contains a 64-bit chunk of elements, each of 'width' bits in size where each element indicates a - match if its lower bit is set, otherwise it indicates a non-match. 'index' tells the database row index of the - first element. You must return true if you chose to 'consume' the chunk or false if not. If not, then Array-finder - will afterwards call match() successive times with pattern == false. - -If pattern == false: - 'index' tells the row index of a single match and 'value' tells its value. Return false to make Array-finder break - its search or return true to let it continue until 'end' or 'limit'. - -Array-finder decides itself if - and when - it wants to pass you an indexpattern. It depends on array bit width, match -frequency, and whether the arithemetic and computations for the given search criteria makes it feasible to construct -such a pattern. -*/ - -// These wrapper functions only exist to enable a possibility to make the compiler see that 'value' and/or 'index' are -// unused, such that caller's computation of these values will not be made. Only works if find_action() and -// find_action_pattern() rewritten as macros. Note: This problem has been fixed in next upcoming array.hpp version -template -bool Array::find_action(size_t index, util::Optional value, QueryState* state, - Callback callback) const -{ - if (action == act_CallbackIdx) - return callback(index); - else - return state->match(index, 0, value); -} -template -bool Array::find_action_pattern(size_t index, uint64_t pattern, QueryState* state, Callback callback) const -{ - static_cast(callback); - if (action == act_CallbackIdx) { - // Possible future optimization: call callback(index) like in above find_action(), in a loop for each bit set - // in 'pattern' - return false; - } - return state->match(index, pattern, 0); -} - - -template -uint64_t Array::cascade(uint64_t a) const -{ - // Takes a chunk of values as argument and sets the least significant bit for each - // element which is zero or non-zero, depending on the template parameter. - // Example for zero=true: - // width == 4 and a = 0x5fd07a107610f610 - // will return: 0x0001000100010001 - - // static values needed for fast population count - const uint64_t m1 = 0x5555555555555555ULL; - - if (width == 1) { - return zero ? ~a : a; - } - else if (width == 2) { - // Masks to avoid spillover between segments in cascades - const uint64_t c1 = ~0ULL / 0x3 * 0x1; - - a |= (a >> 1) & c1; // cascade ones in non-zeroed segments - a &= m1; // isolate single bit in each segment - if (zero) - a ^= m1; // reverse isolated bits if checking for zeroed segments - - return a; - } - else if (width == 4) { - const uint64_t m = ~0ULL / 0xF * 0x1; - - // Masks to avoid spillover between segments in cascades - const uint64_t c1 = ~0ULL / 0xF * 0x7; - const uint64_t c2 = ~0ULL / 0xF * 0x3; - - a |= (a >> 1) & c1; // cascade ones in non-zeroed segments - a |= (a >> 2) & c2; - a &= m; // isolate single bit in each segment - if (zero) - a ^= m; // reverse isolated bits if checking for zeroed segments - - return a; - } - else if (width == 8) { - const uint64_t m = ~0ULL / 0xFF * 0x1; - - // Masks to avoid spillover between segments in cascades - const uint64_t c1 = ~0ULL / 0xFF * 0x7F; - const uint64_t c2 = ~0ULL / 0xFF * 0x3F; - const uint64_t c3 = ~0ULL / 0xFF * 0x0F; - - a |= (a >> 1) & c1; // cascade ones in non-zeroed segments - a |= (a >> 2) & c2; - a |= (a >> 4) & c3; - a &= m; // isolate single bit in each segment - if (zero) - a ^= m; // reverse isolated bits if checking for zeroed segments - - return a; - } - else if (width == 16) { - const uint64_t m = ~0ULL / 0xFFFF * 0x1; - - // Masks to avoid spillover between segments in cascades - const uint64_t c1 = ~0ULL / 0xFFFF * 0x7FFF; - const uint64_t c2 = ~0ULL / 0xFFFF * 0x3FFF; - const uint64_t c3 = ~0ULL / 0xFFFF * 0x0FFF; - const uint64_t c4 = ~0ULL / 0xFFFF * 0x00FF; - - a |= (a >> 1) & c1; // cascade ones in non-zeroed segments - a |= (a >> 2) & c2; - a |= (a >> 4) & c3; - a |= (a >> 8) & c4; - a &= m; // isolate single bit in each segment - if (zero) - a ^= m; // reverse isolated bits if checking for zeroed segments - - return a; - } - - else if (width == 32) { - const uint64_t m = ~0ULL / 0xFFFFFFFF * 0x1; - - // Masks to avoid spillover between segments in cascades - const uint64_t c1 = ~0ULL / 0xFFFFFFFF * 0x7FFFFFFF; - const uint64_t c2 = ~0ULL / 0xFFFFFFFF * 0x3FFFFFFF; - const uint64_t c3 = ~0ULL / 0xFFFFFFFF * 0x0FFFFFFF; - const uint64_t c4 = ~0ULL / 0xFFFFFFFF * 0x00FFFFFF; - const uint64_t c5 = ~0ULL / 0xFFFFFFFF * 0x0000FFFF; - - a |= (a >> 1) & c1; // cascade ones in non-zeroed segments - a |= (a >> 2) & c2; - a |= (a >> 4) & c3; - a |= (a >> 8) & c4; - a |= (a >> 16) & c5; - a &= m; // isolate single bit in each segment - if (zero) - a ^= m; // reverse isolated bits if checking for zeroed segments - - return a; - } - else if (width == 64) { - return (a == 0) == zero; - } - else { - REALM_ASSERT_DEBUG(false); - return uint64_t(-1); - } -} - -// This is the main finding function for Array. Other finding functions are just wrappers around this one. -// Search for 'value' using condition cond (Equal, NotEqual, Less, etc) and call find_action() or -// find_action_pattern() for each match. Break and return if find_action() returns false or 'end' is reached. - -// If nullable_array is set, then find_optimized() will treat the array is being nullable, i.e. it will skip the -// first entry and compare correctly against null, etc. -// -// If find_null is set, it means that we search for a null. In that case, `value` is ignored. If find_null is set, -// then nullable_array must be set too. -template -bool Array::find_optimized(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array, bool find_null) const -{ - REALM_ASSERT(!(find_null && !nullable_array)); - REALM_ASSERT_DEBUG(start <= m_size && (end <= m_size || end == size_t(-1)) && start <= end); - - size_t start2 = start; - cond c; - - if (end == npos) - end = nullable_array ? size() - 1 : size(); - - if (nullable_array) { - // We were called by find() of a nullable array. So skip first entry, take nulls in count, etc, etc. Fixme: - // Huge speed optimizations are possible here! This is a very simple generic method. - for (; start2 < end; start2++) { - int64_t v = get(start2 + 1); - if (c(v, value, v == get(0), find_null)) { - util::Optional v2(v == get(0) ? util::none : util::make_optional(v)); - if (!find_action(start2 + baseindex, v2, state, callback)) - return false; // tell caller to stop aggregating/search - } - } - return true; // tell caller to continue aggregating/search (on next array leafs) - } - - - // Test first few items with no initial time overhead - if (start2 > 0) { - if (m_size > start2 && c(get(start2), value) && start2 < end) { - if (!find_action(start2 + baseindex, get(start2), state, callback)) - return false; - } - - ++start2; - - if (m_size > start2 && c(get(start2), value) && start2 < end) { - if (!find_action(start2 + baseindex, get(start2), state, callback)) - return false; - } - - ++start2; - - if (m_size > start2 && c(get(start2), value) && start2 < end) { - if (!find_action(start2 + baseindex, get(start2), state, callback)) - return false; - } - - ++start2; - - if (m_size > start2 && c(get(start2), value) && start2 < end) { - if (!find_action(start2 + baseindex, get(start2), state, callback)) - return false; - } - - ++start2; - } - - if (!(m_size > start2 && start2 < end)) - return true; - - if (end == size_t(-1)) - end = m_size; - - // Return immediately if no items in array can match (such as if cond == Greater && value == 100 && - // m_ubound == 15) - if (!c.can_match(value, m_lbound, m_ubound)) - return true; - - // optimization if all items are guaranteed to match (such as cond == NotEqual && value == 100 && m_ubound == 15) - if (c.will_match(value, m_lbound, m_ubound)) { - size_t end2; - - if (action == act_CallbackIdx) - end2 = end; - else { - REALM_ASSERT_DEBUG(state->m_match_count < state->m_limit); - size_t process = state->m_limit - state->m_match_count; - end2 = end - start2 > process ? start2 + process : end; - } - if (action == act_Sum || action == act_Max || action == act_Min) { - int64_t res; - size_t res_ndx = 0; - if (action == act_Sum) - res = Array::sum(start2, end2); - if (action == act_Max) - Array::maximum(res, start2, end2, &res_ndx); - if (action == act_Min) - Array::minimum(res, start2, end2, &res_ndx); - - find_action(res_ndx + baseindex, res, state, callback); - // find_action will increment match count by 1, so we need to `-1` from the number of elements that - // we performed the fast Array methods on. - state->m_match_count += end2 - start2 - 1; - } - else if (action == act_Count) { - state->m_state += end2 - start2; - } - else { - for (; start2 < end2; start2++) - if (!find_action(start2 + baseindex, get(start2), state, callback)) - return false; - } - return true; - } - - // finder cannot handle this bitwidth - REALM_ASSERT_3(m_width, !=, 0); - -#if defined(REALM_COMPILER_SSE) - // Only use SSE if payload is at least one SSE chunk (128 bits) in size. Also note taht SSE doesn't support - // Less-than comparison for 64-bit values. - if ((!(std::is_same::value && m_width == 64)) && end - start2 >= sizeof(__m128i) && m_width >= 8 && - (sseavx<42>() || (sseavx<30>() && std::is_same::value && m_width < 64))) { - - // find_sse() must start2 at 16-byte boundary, so search area before that using compare_equality() - __m128i* const a = reinterpret_cast<__m128i*>(round_up(m_data + start2 * bitwidth / 8, sizeof(__m128i))); - __m128i* const b = reinterpret_cast<__m128i*>(round_down(m_data + end * bitwidth / 8, sizeof(__m128i))); - - if (!compare( - value, start2, (reinterpret_cast(a) - m_data) * 8 / no0(bitwidth), baseindex, state, callback)) - return false; - - // Search aligned area with SSE - if (b > a) { - if (sseavx<42>()) { - if (!find_sse( - value, a, b - a, state, - baseindex + ((reinterpret_cast(a) - m_data) * 8 / no0(bitwidth)), callback)) - return false; - } - else if (sseavx<30>()) { - - if (!find_sse( - value, a, b - a, state, - baseindex + ((reinterpret_cast(a) - m_data) * 8 / no0(bitwidth)), callback)) - return false; - } - } - - // Search remainder with compare_equality() - if (!compare( - value, (reinterpret_cast(b) - m_data) * 8 / no0(bitwidth), end, baseindex, state, callback)) - return false; - - return true; - } - else { - return compare(value, start2, end, baseindex, state, callback); - } -#else - return compare(value, start2, end, baseindex, state, callback); -#endif -} - -template -inline int64_t Array::lower_bits() const -{ - if (width == 1) - return 0xFFFFFFFFFFFFFFFFULL; - else if (width == 2) - return 0x5555555555555555ULL; - else if (width == 4) - return 0x1111111111111111ULL; - else if (width == 8) - return 0x0101010101010101ULL; - else if (width == 16) - return 0x0001000100010001ULL; - else if (width == 32) - return 0x0000000100000001ULL; - else if (width == 64) - return 0x0000000000000001ULL; - else { - REALM_ASSERT_DEBUG(false); - return int64_t(-1); - } -} - -// Tests if any chunk in 'value' is 0 -template -inline bool Array::test_zero(uint64_t value) const -{ - uint64_t hasZeroByte; - uint64_t lower = lower_bits(); - uint64_t upper = lower_bits() * 1ULL << (width == 0 ? 0 : (width - 1ULL)); - hasZeroByte = (value - lower) & ~value & upper; - return hasZeroByte != 0; -} - -// Finds first zero (if eq == true) or non-zero (if eq == false) element in v and returns its position. -// IMPORTANT: This function assumes that at least 1 item matches (test this with test_zero() or other means first)! -template -size_t Array::find_zero(uint64_t v) const -{ - size_t start = 0; - uint64_t hasZeroByte; - // Warning free way of computing (1ULL << width) - 1 - uint64_t mask = (width == 64 ? ~0ULL : ((1ULL << (width == 64 ? 0 : width)) - 1ULL)); - - if (eq == (((v >> (width * start)) & mask) == 0)) { - return 0; - } - - // Bisection optimization, speeds up small bitwidths with high match frequency. More partions than 2 do NOT pay - // off because the work done by test_zero() is wasted for the cases where the value exists in first half, but - // useful if it exists in last half. Sweet spot turns out to be the widths and partitions below. - if (width <= 8) { - hasZeroByte = test_zero(v | 0xffffffff00000000ULL); - if (eq ? !hasZeroByte : (v & 0x00000000ffffffffULL) == 0) { - // 00?? -> increasing - start += 64 / no0(width) / 2; - if (width <= 4) { - hasZeroByte = test_zero(v | 0xffff000000000000ULL); - if (eq ? !hasZeroByte : (v & 0x0000ffffffffffffULL) == 0) { - // 000? - start += 64 / no0(width) / 4; - } - } - } - else { - if (width <= 4) { - // ??00 - hasZeroByte = test_zero(v | 0xffffffffffff0000ULL); - if (eq ? !hasZeroByte : (v & 0x000000000000ffffULL) == 0) { - // 0?00 - start += 64 / no0(width) / 4; - } - } - } - } - - while (eq == (((v >> (width * start)) & mask) != 0)) { - // You must only call find_zero() if you are sure that at least 1 item matches - REALM_ASSERT_3(start, <=, 8 * sizeof(v)); - start++; - } - - return start; -} - -// Generate a magic constant used for later bithacks -template -int64_t Array::find_gtlt_magic(int64_t v) const -{ - uint64_t mask1 = (width == 64 ? ~0ULL : ((1ULL << (width == 64 ? 0 : width)) - - 1ULL)); // Warning free way of computing (1ULL << width) - 1 - uint64_t mask2 = mask1 >> 1; - uint64_t magic = gt ? (~0ULL / no0(mask1) * (mask2 - v)) : (~0ULL / no0(mask1) * v); - return magic; -} - -template -bool Array::find_gtlt_fast(uint64_t chunk, uint64_t magic, QueryState* state, size_t baseindex, - Callback callback) const -{ - // Tests if a a chunk of values contains values that are greater (if gt == true) or less (if gt == false) than v. - // Fast, but limited to work when all values in the chunk are positive. - - uint64_t mask1 = (width == 64 ? ~0ULL : ((1ULL << (width == 64 ? 0 : width)) - - 1ULL)); // Warning free way of computing (1ULL << width) - 1 - uint64_t mask2 = mask1 >> 1; - uint64_t m = gt ? (((chunk + magic) | chunk) & ~0ULL / no0(mask1) * (mask2 + 1)) - : ((chunk - magic) & ~chunk & ~0ULL / no0(mask1) * (mask2 + 1)); - size_t p = 0; - while (m) { - if (find_action_pattern(baseindex, m >> (no0(width) - 1), state, callback)) - break; // consumed, so do not call find_action() - - size_t t = first_set_bit64(m) / no0(width); - p += t; - if (!find_action(p + baseindex, (chunk >> (p * width)) & mask1, state, callback)) - return false; - - if ((t + 1) * width == 64) - m = 0; - else - m >>= (t + 1) * width; - p++; - } - - return true; -} - -// clang-format off -template -bool Array::find_gtlt(int64_t v, uint64_t chunk, QueryState* state, size_t baseindex, Callback callback) const -{ - // Find items in 'chunk' that are greater (if gt == true) or smaller (if gt == false) than 'v'. Fixme, __forceinline can make it crash in vS2010 - find out why - if (width == 1) { - for (size_t t = 0; t < 64; t++) { - if (gt ? static_cast(chunk & 0x1) > v : static_cast(chunk & 0x1) < v) {if (!find_action( t + baseindex, static_cast(chunk & 0x1), state, callback)) return false;} - chunk >>= 1; - } - } - else if (width == 2) { - // Alot (50% +) faster than loop/compiler-unrolled loop - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 0 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 1 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 2 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 3 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 4 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 5 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 6 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 7 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 8 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 9 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 10 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 11 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 12 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 13 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 14 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 15 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 16 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 17 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 18 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 19 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 20 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 21 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 22 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 23 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 24 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 25 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 26 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 27 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 28 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 29 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 30 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - if (gt ? static_cast(chunk & 0x3) > v : static_cast(chunk & 0x3) < v) {if (!find_action( 31 + baseindex, static_cast(chunk & 0x3), state, callback)) return false;} - chunk >>= 2; - } - else if (width == 4) { - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 0 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 1 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 2 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 3 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 4 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 5 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 6 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 7 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 8 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 9 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 10 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 11 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 12 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 13 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 14 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - if (gt ? static_cast(chunk & 0xf) > v : static_cast(chunk & 0xf) < v) {if (!find_action( 15 + baseindex, static_cast(chunk & 0xf), state, callback)) return false;} - chunk >>= 4; - } - else if (width == 8) { - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 0 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 1 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 2 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 3 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 4 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 5 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 6 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 7 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 8; - } - else if (width == 16) { - - if (gt ? static_cast(chunk >> 0 * 16) > v : static_cast(chunk >> 0 * 16) < v) {if (!find_action( 0 + baseindex, static_cast(chunk >> 0 * 16), state, callback)) return false;}; - if (gt ? static_cast(chunk >> 1 * 16) > v : static_cast(chunk >> 1 * 16) < v) {if (!find_action( 1 + baseindex, static_cast(chunk >> 1 * 16), state, callback)) return false;}; - if (gt ? static_cast(chunk >> 2 * 16) > v : static_cast(chunk >> 2 * 16) < v) {if (!find_action( 2 + baseindex, static_cast(chunk >> 2 * 16), state, callback)) return false;}; - if (gt ? static_cast(chunk >> 3 * 16) > v : static_cast(chunk >> 3 * 16) < v) {if (!find_action( 3 + baseindex, static_cast(chunk >> 3 * 16), state, callback)) return false;}; - } - else if (width == 32) { - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 0 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 32; - if (gt ? static_cast(chunk) > v : static_cast(chunk) < v) {if (!find_action( 1 + baseindex, static_cast(chunk), state, callback)) return false;} - chunk >>= 32; - } - else if (width == 64) { - if (gt ? static_cast(v) > v : static_cast(v) < v) {if (!find_action( 0 + baseindex, static_cast(v), state, callback)) return false;}; - } - - return true; -} -// clang-format on - -/// Find items in this Array that are equal (eq == true) or different (eq = false) from 'value' -template -inline bool Array::compare_equality(int64_t value, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const -{ - REALM_ASSERT_DEBUG(start <= m_size && (end <= m_size || end == size_t(-1)) && start <= end); - - size_t ee = round_up(start, 64 / no0(width)); - ee = ee > end ? end : ee; - for (; start < ee; ++start) - if (eq ? (get(start) == value) : (get(start) != value)) { - if (!find_action(start + baseindex, get(start), state, callback)) - return false; - } - - if (start >= end) - return true; - - if (width != 32 && width != 64) { - const int64_t* p = reinterpret_cast(m_data + (start * width / 8)); - const int64_t* const e = reinterpret_cast(m_data + (end * width / 8)) - 1; - const uint64_t mask = (width == 64 ? ~0ULL : ((1ULL << (width == 64 ? 0 : width)) - - 1ULL)); // Warning free way of computing (1ULL << width) - 1 - const uint64_t valuemask = - ~0ULL / no0(mask) * (value & mask); // the "== ? :" is to avoid division by 0 compiler error - - while (p < e) { - uint64_t chunk = *p; - uint64_t v2 = chunk ^ valuemask; - start = (p - reinterpret_cast(m_data)) * 8 * 8 / no0(width); - size_t a = 0; - - while (eq ? test_zero(v2) : v2) { - - if (find_action_pattern(start + baseindex, cascade(v2), state, callback)) - break; // consumed - - size_t t = find_zero(v2); - a += t; - - if (a >= 64 / no0(width)) - break; - - if (!find_action(a + start + baseindex, get(start + t), state, callback)) - return false; - v2 >>= (t + 1) * width; - a += 1; - } - - ++p; - } - - // Loop ended because we are near end or end of array. No need to optimize search in remainder in this case - // because end of array means that - // lots of search work has taken place prior to ending here. So time spent searching remainder is relatively - // tiny - start = (p - reinterpret_cast(m_data)) * 8 * 8 / no0(width); - } - - while (start < end) { - if (eq ? get(start) == value : get(start) != value) { - if (!find_action(start + baseindex, get(start), state, callback)) - return false; - } - ++start; - } - - return true; -} - -// There exists a couple of find() functions that take more or less template arguments. Always call the one that -// takes as most as possible to get best performance. - -// This is the one installed into the m_vtable->finder slots. -template -bool Array::find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state) const -{ - return find(value, start, end, baseindex, state, CallbackDummy()); -} - -template -bool Array::find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array, bool find_null) const -{ - REALM_TEMPEX4(return find, cond, action, m_width, Callback, - (value, start, end, baseindex, state, callback, nullable_array, find_null)); -} - -template -bool Array::find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback, bool nullable_array, bool find_null) const -{ - return find_optimized(value, start, end, baseindex, state, callback, - nullable_array, find_null); -} - -#ifdef REALM_COMPILER_SSE -// 'items' is the number of 16-byte SSE chunks. Returns index of packed element relative to first integer of first -// chunk -template -bool Array::find_sse(int64_t value, __m128i* data, size_t items, QueryState* state, size_t baseindex, - Callback callback) const -{ - __m128i search = {0}; - - if (width == 8) - search = _mm_set1_epi8(static_cast(value)); - else if (width == 16) - search = _mm_set1_epi16(static_cast(value)); - else if (width == 32) - search = _mm_set1_epi32(static_cast(value)); - else if (width == 64) { - if (std::is_same::value) - REALM_ASSERT(false); - else - search = _mm_set_epi64x(value, value); - } - - return find_sse_intern(data, &search, items, state, baseindex, callback); -} - -// Compares packed action_data with packed data (equal, less, etc) and performs aggregate action (max, min, sum, -// find_all, etc) on value inside action_data for first match, if any -template -REALM_FORCEINLINE bool Array::find_sse_intern(__m128i* action_data, __m128i* data, size_t items, - QueryState* state, size_t baseindex, Callback callback) const -{ - size_t i = 0; - __m128i compare_result = {0}; - unsigned int resmask; - - // Search loop. Unrolling it has been tested to NOT increase performance (apparently mem bound) - for (i = 0; i < items; ++i) { - // equal / not-equal - if (std::is_same::value || std::is_same::value) { - if (width == 8) - compare_result = _mm_cmpeq_epi8(action_data[i], *data); - if (width == 16) - compare_result = _mm_cmpeq_epi16(action_data[i], *data); - if (width == 32) - compare_result = _mm_cmpeq_epi32(action_data[i], *data); - if (width == 64) { - compare_result = _mm_cmpeq_epi64(action_data[i], *data); // SSE 4.2 only - } - } - - // greater - else if (std::is_same::value) { - if (width == 8) - compare_result = _mm_cmpgt_epi8(action_data[i], *data); - if (width == 16) - compare_result = _mm_cmpgt_epi16(action_data[i], *data); - if (width == 32) - compare_result = _mm_cmpgt_epi32(action_data[i], *data); - if (width == 64) - compare_result = _mm_cmpgt_epi64(action_data[i], *data); - } - // less - else if (std::is_same::value) { - if (width == 8) - compare_result = _mm_cmplt_epi8(action_data[i], *data); - else if (width == 16) - compare_result = _mm_cmplt_epi16(action_data[i], *data); - else if (width == 32) - compare_result = _mm_cmplt_epi32(action_data[i], *data); - else - REALM_ASSERT(false); - } - - resmask = _mm_movemask_epi8(compare_result); - - if (std::is_same::value) - resmask = ~resmask & 0x0000ffff; - - size_t s = i * sizeof(__m128i) * 8 / no0(width); - - while (resmask != 0) { - - uint64_t upper = lower_bits() << (no0(width / 8) - 1); - uint64_t pattern = - resmask & - upper; // fixme, bits at wrong offsets. Only OK because we only use them in 'count' aggregate - if (find_action_pattern(s + baseindex, pattern, state, callback)) - break; - - size_t idx = first_set_bit(resmask) * 8 / no0(width); - s += idx; - if (!find_action( - s + baseindex, get_universal(reinterpret_cast(action_data), s), state, callback)) - return false; - resmask >>= (idx + 1) * no0(width) / 8; - ++s; - } - } - - return true; -} -#endif // REALM_COMPILER_SSE - -template -bool Array::compare_leafs(const Array* foreign, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const -{ - cond c; - REALM_ASSERT_3(start, <=, end); - if (start == end) - return true; - - - int64_t v; - - // We can compare first element without checking for out-of-range - v = get(start); - if (c(v, foreign->get(start))) { - if (!find_action(start + baseindex, v, state, callback)) - return false; - } - - start++; - - if (start + 3 < end) { - v = get(start); - if (c(v, foreign->get(start))) - if (!find_action(start + baseindex, v, state, callback)) - return false; - - v = get(start + 1); - if (c(v, foreign->get(start + 1))) - if (!find_action(start + 1 + baseindex, v, state, callback)) - return false; - - v = get(start + 2); - if (c(v, foreign->get(start + 2))) - if (!find_action(start + 2 + baseindex, v, state, callback)) - return false; - - start += 3; - } - else if (start == end) { - return true; - } - - bool r; - REALM_TEMPEX4(r = compare_leafs, cond, action, m_width, Callback, - (foreign, start, end, baseindex, state, callback)) - return r; -} - - -template -bool Array::compare_leafs(const Array* foreign, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const -{ - size_t fw = foreign->m_width; - bool r; - REALM_TEMPEX5(r = compare_leafs_4, cond, action, width, Callback, fw, - (foreign, start, end, baseindex, state, callback)) - return r; -} - - -template -bool Array::compare_leafs_4(const Array* foreign, size_t start, size_t end, size_t baseindex, - QueryState* state, Callback callback) const -{ - cond c; - char* foreign_m_data = foreign->m_data; - - if (width == 0 && foreign_width == 0) { - if (c(0, 0)) { - while (start < end) { - if (!find_action(start + baseindex, 0, state, callback)) - return false; - start++; - } - } - else { - return true; - } - } - - -#if defined(REALM_COMPILER_SSE) - if (sseavx<42>() && width == foreign_width && (width == 8 || width == 16 || width == 32)) { - // We can only use SSE if both bitwidths are equal and above 8 bits and all values are signed - while (start < end && (((reinterpret_cast(m_data) & 0xf) * 8 + start * width) % (128) != 0)) { - int64_t v = get_universal(m_data, start); - int64_t fv = get_universal(foreign_m_data, start); - if (c(v, fv)) { - if (!find_action(start + baseindex, v, state, callback)) - return false; - } - start++; - } - if (start == end) - return true; - - - size_t sse_items = (end - start) * width / 128; - size_t sse_end = start + sse_items * 128 / no0(width); - - while (start < sse_end) { - __m128i* a = reinterpret_cast<__m128i*>(m_data + start * width / 8); - __m128i* b = reinterpret_cast<__m128i*>(foreign_m_data + start * width / 8); - - bool continue_search = - find_sse_intern(a, b, 1, state, baseindex + start, callback); - - if (!continue_search) - return false; - - start += 128 / no0(width); - } - } -#endif - - while (start < end) { - int64_t v = get_universal(m_data, start); - int64_t fv = get_universal(foreign_m_data, start); - - if (c(v, fv)) { - if (!find_action(start + baseindex, v, state, callback)) - return false; - } - - start++; - } - - return true; -} - - -template -bool Array::compare(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const -{ - bool ret = false; - - if (std::is_same::value) - ret = compare_equality(value, start, end, baseindex, state, callback); - else if (std::is_same::value) - ret = compare_equality(value, start, end, baseindex, state, callback); - else if (std::is_same::value) - ret = compare_relation(value, start, end, baseindex, state, callback); - else if (std::is_same::value) - ret = compare_relation(value, start, end, baseindex, state, callback); - else - REALM_ASSERT_DEBUG(false); - - return ret; -} - -template -bool Array::compare_relation(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const -{ - REALM_ASSERT(start <= m_size && (end <= m_size || end == size_t(-1)) && start <= end); - uint64_t mask = (bitwidth == 64 ? ~0ULL : ((1ULL << (bitwidth == 64 ? 0 : bitwidth)) - - 1ULL)); // Warning free way of computing (1ULL << width) - 1 - - size_t ee = round_up(start, 64 / no0(bitwidth)); - ee = ee > end ? end : ee; - for (; start < ee; start++) { - if (gt ? (get(start) > value) : (get(start) < value)) { - if (!find_action(start + baseindex, get(start), state, callback)) - return false; - } - } - - if (start >= end) - return true; // none found, continue (return true) regardless what find_action() would have returned on match - - const int64_t* p = reinterpret_cast(m_data + (start * bitwidth / 8)); - const int64_t* const e = reinterpret_cast(m_data + (end * bitwidth / 8)) - 1; - - // Matches are rare enough to setup fast linear search for remaining items. We use - // bit hacks from http://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord - - if (bitwidth == 1 || bitwidth == 2 || bitwidth == 4 || bitwidth == 8 || bitwidth == 16) { - uint64_t magic = find_gtlt_magic(value); - - // Bit hacks only work if searched item has its most significant bit clear for 'greater than' or - // 'item <= 1 << bitwidth' for 'less than' - if (value != int64_t((magic & mask)) && value >= 0 && bitwidth >= 2 && - value <= static_cast((mask >> 1) - (gt ? 1 : 0))) { - // 15 ms - while (p < e) { - uint64_t upper = lower_bits() << (no0(bitwidth) - 1); - - const int64_t v = *p; - size_t idx; - - // Bit hacks only works if all items in chunk have their most significant bit clear. Test this: - upper = upper & v; - - if (!upper) { - idx = find_gtlt_fast( - v, magic, state, (p - reinterpret_cast(m_data)) * 8 * 8 / no0(bitwidth) + baseindex, - callback); - } - else - idx = find_gtlt( - value, v, state, (p - reinterpret_cast(m_data)) * 8 * 8 / no0(bitwidth) + baseindex, - callback); - - if (!idx) - return false; - ++p; - } - } - else { - // 24 ms - while (p < e) { - int64_t v = *p; - if (!find_gtlt( - value, v, state, (p - reinterpret_cast(m_data)) * 8 * 8 / no0(bitwidth) + baseindex, - callback)) - return false; - ++p; - } - } - start = (p - reinterpret_cast(m_data)) * 8 * 8 / no0(bitwidth); - } - - // matchcount logic in SIMD no longer pays off for 32/64 bit ints because we have just 4/2 elements - - // Test unaligned end and/or values of width > 16 manually - while (start < end) { - if (gt ? get(start) > value : get(start) < value) { - if (!find_action(start + baseindex, get(start), state, callback)) - return false; - } - ++start; - } - return true; -} - -template -size_t Array::find_first(int64_t value, size_t start, size_t end) const -{ - REALM_ASSERT(start <= m_size && (end <= m_size || end == size_t(-1)) && start <= end); - QueryState state; - state.init(act_ReturnFirst, nullptr, - 1); // todo, would be nice to avoid this in order to speed up find_first loops - Finder finder = m_vtable->finder[cond::condition]; - (this->*finder)(value, start, end, 0, &state); - - return static_cast(state.m_state); -} - -//************************************************************************************* -// Finding code ends * -//************************************************************************************* - - -} // namespace realm - -#endif // REALM_ARRAY_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_basic.hpp b/Example/Pods/Realm/include/core/realm/array_basic.hpp deleted file mode 100644 index 317f11f..0000000 --- a/Example/Pods/Realm/include/core/realm/array_basic.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_BASIC_HPP -#define REALM_ARRAY_BASIC_HPP - -#include - -namespace realm { - -/// A BasicArray can currently only be used for simple unstructured -/// types like float, double. -template -class BasicArray : public Array { -public: - explicit BasicArray(Allocator&) noexcept; - ~BasicArray() noexcept override - { - } - - T get(size_t ndx) const noexcept; - bool is_null(size_t ndx) const noexcept; - void add(T value); - void set(size_t ndx, T value); - void set_null(size_t ndx); - void insert(size_t ndx, T value); - void erase(size_t ndx); - void truncate(size_t size); - void clear(); - - size_t find_first(T value, size_t begin = 0, size_t end = npos) const; - void find_all(IntegerColumn* result, T value, size_t add_offset = 0, size_t begin = 0, size_t end = npos) const; - - size_t count(T value, size_t begin = 0, size_t end = npos) const; - bool maximum(T& result, size_t begin = 0, size_t end = npos) const; - bool minimum(T& result, size_t begin = 0, size_t end = npos) const; - - /// Compare two arrays for equality. - bool compare(const BasicArray&) const; - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static T get(const char* header, size_t ndx) noexcept; - - ref_type bptree_leaf_insert(size_t ndx, T, TreeInsertBase& state); - - size_t lower_bound(T value) const noexcept; - size_t upper_bound(T value) const noexcept; - - /// Construct a basic array of the specified size and return just - /// the reference to the underlying memory. All elements will be - /// initialized to `T()`. - static MemRef create_array(size_t size, Allocator&); - - static MemRef create_array(Array::Type leaf_type, bool context_flag, size_t size, T value, Allocator&); - - /// Create a new empty array and attach this accessor to it. This - /// does not modify the parent reference information of this - /// accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(Array::Type = type_Normal, bool context_flag = false); - - /// Construct a copy of the specified slice of this basic array - /// using the specified target allocator. - MemRef slice(size_t offset, size_t size, Allocator& target_alloc) const; - MemRef slice_and_clone_children(size_t offset, size_t size, Allocator& target_alloc) const; - -#ifdef REALM_DEBUG - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - -private: - size_t find(T target, size_t begin, size_t end) const; - - size_t calc_byte_len(size_t count, size_t width) const override; - virtual size_t calc_item_count(size_t bytes, size_t width) const noexcept override; - - template - bool minmax(T& result, size_t begin, size_t end) const; - - /// Calculate the total number of bytes needed for a basic array - /// with the specified number of elements. This includes the size - /// of the header. The result will be upwards aligned to the - /// closest 8-byte boundary. - static size_t calc_aligned_byte_size(size_t size); -}; - - -// Class typedefs for BasicArray's: ArrayFloat and ArrayDouble -typedef BasicArray ArrayFloat; -typedef BasicArray ArrayDouble; - -} // namespace realm - -#include - -#endif // REALM_ARRAY_BASIC_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_basic_tpl.hpp b/Example/Pods/Realm/include/core/realm/array_basic_tpl.hpp deleted file mode 100644 index 99b21d1..0000000 --- a/Example/Pods/Realm/include/core/realm/array_basic_tpl.hpp +++ /dev/null @@ -1,457 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_BASIC_TPL_HPP -#define REALM_ARRAY_BASIC_TPL_HPP - -#include -#include -#include -#include - -#include - -namespace realm { - -template -inline BasicArray::BasicArray(Allocator& allocator) noexcept - : Array(allocator) -{ -} - -template -inline MemRef BasicArray::create_array(size_t init_size, Allocator& allocator) -{ - size_t byte_size_0 = calc_aligned_byte_size(init_size); // Throws - // Adding zero to Array::initial_capacity to avoid taking the - // address of that member - size_t byte_size = std::max(byte_size_0, Array::initial_capacity + 0); // Throws - - MemRef mem = allocator.alloc(byte_size); // Throws - - bool is_inner_bptree_node = false; - bool has_refs = false; - bool context_flag = false; - int width = sizeof(T); - init_header(mem.get_addr(), is_inner_bptree_node, has_refs, context_flag, wtype_Multiply, width, init_size, - byte_size); - - return mem; -} - - -template -inline MemRef BasicArray::create_array(Array::Type type, bool context_flag, size_t init_size, T value, - Allocator& allocator) -{ - REALM_ASSERT(type == Array::type_Normal); - REALM_ASSERT(!context_flag); - MemRef mem = create_array(init_size, allocator); - if (init_size) { - BasicArray tmp(allocator); - tmp.init_from_mem(mem); - for (size_t i = 0; i < init_size; ++i) { - tmp.set(i, value); - } - return tmp.get_mem(); - } - return mem; -} - - -template -inline void BasicArray::create(Array::Type type, bool context_flag) -{ - REALM_ASSERT(type == Array::type_Normal); - REALM_ASSERT(!context_flag); - size_t length = 0; - MemRef mem = create_array(length, get_alloc()); // Throws - init_from_mem(mem); -} - - -template -MemRef BasicArray::slice(size_t offset, size_t slice_size, Allocator& target_alloc) const -{ - REALM_ASSERT(is_attached()); - - // FIXME: This can be optimized as a single contiguous copy - // operation. - BasicArray array_slice(target_alloc); - _impl::ShallowArrayDestroyGuard dg(&array_slice); - array_slice.create(); // Throws - size_t begin = offset; - size_t end = offset + slice_size; - for (size_t i = begin; i != end; ++i) { - T value = get(i); - array_slice.add(value); // Throws - } - dg.release(); - return array_slice.get_mem(); -} - -template -MemRef BasicArray::slice_and_clone_children(size_t offset, size_t slice_size, Allocator& target_alloc) const -{ - // BasicArray never contains refs, so never has children. - return slice(offset, slice_size, target_alloc); -} - - -template -inline void BasicArray::add(T value) -{ - insert(m_size, value); -} - - -template -inline T BasicArray::get(size_t ndx) const noexcept -{ - return *(reinterpret_cast(m_data) + ndx); -} - - -template -inline bool BasicArray::is_null(size_t ndx) const noexcept -{ - // FIXME: This assumes BasicArray will only ever be instantiated for float-like T. - static_assert(realm::is_any::value, "T can only be float or double"); - auto x = get(ndx); - return null::is_null_float(x); -} - - -template -inline T BasicArray::get(const char* header, size_t ndx) noexcept -{ - const char* data = get_data_from_header(header); - // This casting assumes that T can be aliged on an 8-bype - // boundary (since data is aligned on an 8-byte boundary.) - return *(reinterpret_cast(data) + ndx); -} - - -template -inline void BasicArray::set(size_t ndx, T value) -{ - REALM_ASSERT_3(ndx, <, m_size); - - // Check if we need to copy before modifying - copy_on_write(); // Throws - - // Set the value - T* data = reinterpret_cast(m_data) + ndx; - *data = value; -} - -template -inline void BasicArray::set_null(size_t ndx) -{ - // FIXME: This assumes BasicArray will only ever be instantiated for float-like T. - set(ndx, null::get_null_float()); -} - -template -void BasicArray::insert(size_t ndx, T value) -{ - REALM_ASSERT_3(ndx, <=, m_size); - - // Check if we need to copy before modifying - copy_on_write(); // Throws - - // Make room for the new value - alloc(m_size + 1, m_width); // Throws - - // Move values below insertion - if (ndx != m_size) { - char* src_begin = m_data + ndx * m_width; - char* src_end = m_data + m_size * m_width; - char* dst_end = src_end + m_width; - std::copy_backward(src_begin, src_end, dst_end); - } - - // Set the value - T* data = reinterpret_cast(m_data) + ndx; - *data = value; - - ++m_size; -} - -template -void BasicArray::erase(size_t ndx) -{ - REALM_ASSERT_3(ndx, <, m_size); - - // Check if we need to copy before modifying - copy_on_write(); // Throws - - // move data under deletion up - if (ndx < m_size - 1) { - char* dst_begin = m_data + ndx * m_width; - const char* src_begin = dst_begin + m_width; - const char* src_end = m_data + m_size * m_width; - std::copy(src_begin, src_end, dst_begin); - } - - // Update size (also in header) - --m_size; - set_header_size(m_size); -} - -template -void BasicArray::truncate(size_t to_size) -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT_3(to_size, <=, m_size); - - copy_on_write(); // Throws - - // Update size in accessor and in header. This leaves the capacity - // unchanged. - m_size = to_size; - set_header_size(to_size); -} - -template -inline void BasicArray::clear() -{ - truncate(0); // Throws -} - -template -bool BasicArray::compare(const BasicArray& a) const -{ - size_t n = size(); - if (a.size() != n) - return false; - const T* data_1 = reinterpret_cast(m_data); - const T* data_2 = reinterpret_cast(a.m_data); - return std::equal(data_1, data_1 + n, data_2); -} - - -template -size_t BasicArray::calc_byte_len(size_t for_size, size_t) const -{ - // FIXME: Consider calling `calc_aligned_byte_size(size)` - // instead. Note however, that calc_byte_len() is supposed to return - // the unaligned byte size. It is probably the case that no harm - // is done by returning the aligned version, and most callers of - // calc_byte_len() will actually benefit if calc_byte_len() was - // changed to always return the aligned byte size. - return header_size + for_size * sizeof(T); -} - -template -size_t BasicArray::calc_item_count(size_t bytes, size_t) const noexcept -{ - size_t bytes_without_header = bytes - header_size; - return bytes_without_header / sizeof(T); -} - -template -size_t BasicArray::find(T value, size_t begin, size_t end) const -{ - if (end == npos) - end = m_size; - REALM_ASSERT(begin <= m_size && end <= m_size && begin <= end); - const T* data = reinterpret_cast(m_data); - const T* i = std::find(data + begin, data + end, value); - return i == data + end ? not_found : size_t(i - data); -} - -template -inline size_t BasicArray::find_first(T value, size_t begin, size_t end) const -{ - return this->find(value, begin, end); -} - -template -void BasicArray::find_all(IntegerColumn* result, T value, size_t add_offset, size_t begin, size_t end) const -{ - size_t first = begin - 1; - for (;;) { - first = this->find(value, first + 1, end); - if (first == not_found) - break; - - Array::add_to_column(result, first + add_offset); - } -} - -template -size_t BasicArray::count(T value, size_t begin, size_t end) const -{ - if (end == npos) - end = m_size; - REALM_ASSERT(begin <= m_size && end <= m_size && begin <= end); - const T* data = reinterpret_cast(m_data); - return std::count(data + begin, data + end, value); -} - -#if 0 -// currently unused -template -double BasicArray::sum(size_t begin, size_t end) const -{ - if (end == npos) - end = m_size; - REALM_ASSERT(begin <= m_size && end <= m_size && begin <= end); - const T* data = reinterpret_cast(m_data); - return std::accumulate(data + begin, data + end, double(0)); -} -#endif - -template -template -bool BasicArray::minmax(T& result, size_t begin, size_t end) const -{ - if (end == npos) - end = m_size; - if (m_size == 0) - return false; - REALM_ASSERT(begin < m_size && end <= m_size && begin < end); - - T m = get(begin); - ++begin; - for (; begin < end; ++begin) { - T val = get(begin); - if (find_max ? val > m : val < m) - m = val; - } - result = m; - return true; -} - -template -bool BasicArray::maximum(T& result, size_t begin, size_t end) const -{ - return minmax(result, begin, end); -} - -template -bool BasicArray::minimum(T& result, size_t begin, size_t end) const -{ - return minmax(result, begin, end); -} - - -template -ref_type BasicArray::bptree_leaf_insert(size_t ndx, T value, TreeInsertBase& state) -{ - size_t leaf_size = size(); - REALM_ASSERT_3(leaf_size, <=, REALM_MAX_BPNODE_SIZE); - if (leaf_size < ndx) - ndx = leaf_size; - if (REALM_LIKELY(leaf_size < REALM_MAX_BPNODE_SIZE)) { - insert(ndx, value); - return 0; // Leaf was not split - } - - // Split leaf node - BasicArray new_leaf(get_alloc()); - new_leaf.create(); // Throws - if (ndx == leaf_size) { - new_leaf.add(value); - state.m_split_offset = ndx; - } - else { - // FIXME: Could be optimized by first resizing the target - // array, then copy elements with std::copy(). - for (size_t i = ndx; i != leaf_size; ++i) - new_leaf.add(get(i)); - truncate(ndx); - add(value); - state.m_split_offset = ndx + 1; - } - state.m_split_size = leaf_size + 1; - return new_leaf.get_ref(); -} - -template -inline size_t BasicArray::lower_bound(T value) const noexcept -{ - const T* begin = reinterpret_cast(m_data); - const T* end = begin + size(); - return std::lower_bound(begin, end, value) - begin; -} - -template -inline size_t BasicArray::upper_bound(T value) const noexcept -{ - const T* begin = reinterpret_cast(m_data); - const T* end = begin + size(); - return std::upper_bound(begin, end, value) - begin; -} - -template -inline size_t BasicArray::calc_aligned_byte_size(size_t size) -{ - size_t max = std::numeric_limits::max(); - size_t max_2 = max & ~size_t(7); // Allow for upwards 8-byte alignment - if (size > (max_2 - header_size) / sizeof(T)) - throw std::runtime_error("Byte size overflow"); - size_t byte_size = header_size + size * sizeof(T); - REALM_ASSERT_3(byte_size, >, 0); - size_t aligned_byte_size = ((byte_size - 1) | 7) + 1; // 8-byte alignment - return aligned_byte_size; -} - - -#ifdef REALM_DEBUG - -// LCOV_EXCL_START -template -void BasicArray::to_dot(std::ostream& out, StringData title) const -{ - ref_type ref = get_ref(); - if (title.size() != 0) { - out << "subgraph cluster_" << ref << " {\n"; - out << " label = \"" << title << "\";\n"; - out << " color = white;\n"; - } - - out << "n" << std::hex << ref << std::dec << "[shape=none,label=<"; - out << "
\n"; - - // Header - out << "\n"; - - // Values - size_t n = m_size; - for (size_t i = 0; i != n; ++i) - out << "\n"; - - out << "
"; - out << "0x" << std::hex << ref << std::dec << "
"; - out << "
" << get(i) << "
>];\n"; - - if (title.size() != 0) - out << "}\n"; - - to_dot_parent_edge(out); -} -// LCOV_EXCL_STOP - -#endif // REALM_DEBUG - - -} // namespace realm - -#endif // REALM_ARRAY_BASIC_TPL_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_binary.hpp b/Example/Pods/Realm/include/core/realm/array_binary.hpp deleted file mode 100644 index 414b0df..0000000 --- a/Example/Pods/Realm/include/core/realm/array_binary.hpp +++ /dev/null @@ -1,255 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_BINARY_HPP -#define REALM_ARRAY_BINARY_HPP - -#include -#include -#include -#include - -namespace realm { - -/* -STORAGE FORMAT ---------------------------------------------------------------------------------------- -ArrayBinary stores binary elements using two ArrayInteger and one ArrayBlob. The ArrayBlob can only store one -single concecutive array of bytes (contrary to its 'Array' name that misleadingly indicates it could store multiple -elements). - -Assume we have the strings "a", "", "abc", null, "ab". Then the three arrays will contain: - -ArrayInteger m_offsets 1, 1, 5, 5, 6 -ArrayBlob m_blob aabcab -ArrayInteger m_nulls 0, 0, 0, 1, 0 // 1 indicates null, 0 indicates non-null - -So for each element the ArrayInteger, the ArrayInteger points into the ArrayBlob at the position of the first -byte of the next element. - -m_nulls is always present (except for old database files; see below), so any ArrayBinary is always nullable! -The nullable property (such as throwing exception upon set(null) on non-nullable column, etc) is handled on -column level only. - -DATABASE FILE VERSION CHANGES ---------------------------------------------------------------------------------------- -Old database files do not have any m_nulls array. To be backwardscompatible, many methods will have tests like -`if(Array::size() == 3)` and have a backwards compatible code paths for these (e.g. avoid writing to m_nulls -in set(), etc). This way no file format upgrade is needed to support nulls for BinaryData. -*/ - -class ArrayBinary : public Array { -public: - explicit ArrayBinary(Allocator&) noexcept; - ~ArrayBinary() noexcept override - { - } - - /// Create a new empty binary array and attach this accessor to - /// it. This does not modify the parent reference information of - /// this accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(); - - // Old database files will not have the m_nulls array, so we need code paths for - // backwards compatibility for these cases. - bool legacy_array_type() const noexcept; - - //@{ - /// Overriding functions of Array - void init_from_ref(ref_type) noexcept; - void init_from_mem(MemRef) noexcept; - void init_from_parent() noexcept; - //@} - - bool is_empty() const noexcept; - size_t size() const noexcept; - - BinaryData get(size_t ndx) const noexcept; - size_t read(size_t ndx, size_t pos, char* buffer, size_t max_size) const noexcept; - - void add(BinaryData value, bool add_zero_term = false); - void set(size_t ndx, BinaryData value, bool add_zero_term = false); - void insert(size_t ndx, BinaryData value, bool add_zero_term = false); - void erase(size_t ndx); - void truncate(size_t new_size); - void clear(); - void destroy(); - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static BinaryData get(const char* header, size_t ndx, Allocator&) noexcept; - - ref_type bptree_leaf_insert(size_t ndx, BinaryData, bool add_zero_term, TreeInsertBase& state); - - static size_t get_size_from_header(const char*, Allocator&) noexcept; - - /// Construct a binary array of the specified size and return just - /// the reference to the underlying memory. All elements will be - /// initialized to the binary value `defaults`, which can be either - /// null or zero-length non-null (value with size > 0 is not allowed as - /// initialization value). - static MemRef create_array(size_t size, Allocator&, BinaryData defaults); - - /// Construct a copy of the specified slice of this binary array - /// using the specified target allocator. - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - -#ifdef REALM_DEBUG - void to_dot(std::ostream&, bool is_strings, StringData title = StringData()) const; -#endif - bool update_from_parent(size_t old_baseline) noexcept; - -private: - ArrayInteger m_offsets; - ArrayBlob m_blob; - ArrayInteger m_nulls; -}; - - -// Implementation: - -inline ArrayBinary::ArrayBinary(Allocator& allocator) noexcept - : Array(allocator) - , m_offsets(allocator) - , m_blob(allocator) - , m_nulls(allocator) -{ - m_offsets.set_parent(this, 0); - m_blob.set_parent(this, 1); - m_nulls.set_parent(this, 2); -} - -inline void ArrayBinary::create() -{ - size_t init_size = 0; - BinaryData defaults = BinaryData{}; // This init value is ignored because size = 0 - MemRef mem = create_array(init_size, get_alloc(), defaults); // Throws - init_from_mem(mem); -} - -inline void ArrayBinary::init_from_ref(ref_type ref) noexcept -{ - REALM_ASSERT(ref); - char* header = get_alloc().translate(ref); - init_from_mem(MemRef(header, ref, m_alloc)); -} - -inline void ArrayBinary::init_from_parent() noexcept -{ - ref_type ref = get_ref_from_parent(); - init_from_ref(ref); -} - -inline bool ArrayBinary::is_empty() const noexcept -{ - return m_offsets.is_empty(); -} - -// Old database files will not have the m_nulls array, so we need code paths for -// backwards compatibility for these cases. We can test if m_nulls exists by looking -// at number of references in this ArrayBinary. -inline bool ArrayBinary::legacy_array_type() const noexcept -{ - if (Array::size() == 3) - return false; // New database file - else if (Array::size() == 2) - return true; // Old database file - else - REALM_ASSERT(false); // Should never happen - return false; -} - -inline size_t ArrayBinary::size() const noexcept -{ - return m_offsets.size(); -} - -inline BinaryData ArrayBinary::get(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_offsets.size()); - - if (!legacy_array_type() && m_nulls.get(ndx)) { - return BinaryData(); - } - else { - size_t begin = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0; - size_t end = to_size_t(m_offsets.get(ndx)); - - BinaryData bd = BinaryData(m_blob.get(begin), end - begin); - // Old database file (non-nullable column should never return null) - REALM_ASSERT(!bd.is_null()); - return bd; - } -} - -inline void ArrayBinary::truncate(size_t new_size) -{ - REALM_ASSERT_3(new_size, <, m_offsets.size()); - - size_t blob_size = new_size ? to_size_t(m_offsets.get(new_size - 1)) : 0; - - m_offsets.truncate(new_size); - m_blob.truncate(blob_size); - if (!legacy_array_type()) - m_nulls.truncate(new_size); -} - -inline void ArrayBinary::clear() -{ - m_blob.clear(); - m_offsets.clear(); - if (!legacy_array_type()) - m_nulls.clear(); -} - -inline void ArrayBinary::destroy() -{ - m_blob.destroy(); - m_offsets.destroy(); - if (!legacy_array_type()) - m_nulls.destroy(); - Array::destroy(); -} - -inline size_t ArrayBinary::get_size_from_header(const char* header, Allocator& alloc) noexcept -{ - ref_type offsets_ref = to_ref(Array::get(header, 0)); - const char* offsets_header = alloc.translate(offsets_ref); - return Array::get_size_from_header(offsets_header); -} - -inline bool ArrayBinary::update_from_parent(size_t old_baseline) noexcept -{ - bool res = Array::update_from_parent(old_baseline); - if (res) { - m_blob.update_from_parent(old_baseline); - m_offsets.update_from_parent(old_baseline); - if (!legacy_array_type()) - m_nulls.update_from_parent(old_baseline); - } - return res; -} - -} // namespace realm - -#endif // REALM_ARRAY_BINARY_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_blob.hpp b/Example/Pods/Realm/include/core/realm/array_blob.hpp deleted file mode 100644 index 7fcf181..0000000 --- a/Example/Pods/Realm/include/core/realm/array_blob.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_BLOB_HPP -#define REALM_ARRAY_BLOB_HPP - -#include - -namespace realm { - - -class ArrayBlob : public Array { -public: - static constexpr size_t max_binary_size = 0xFFFFF8 - Array::header_size; - - explicit ArrayBlob(Allocator&) noexcept; - ~ArrayBlob() noexcept override - { - } - - const char* get(size_t index) const noexcept; - BinaryData get_at(size_t& pos) const noexcept; - bool is_null(size_t index) const noexcept; - ref_type add(const char* data, size_t data_size, bool add_zero_term = false); - void insert(size_t pos, const char* data, size_t data_size, bool add_zero_term = false); - ref_type replace(size_t begin, size_t end, const char* data, size_t data_size, bool add_zero_term = false); - void erase(size_t begin, size_t end); - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static const char* get(const char* header, size_t index) noexcept; - - /// Create a new empty blob (binary) array and attach this - /// accessor to it. This does not modify the parent reference - /// information of this accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(); - - /// Construct a blob of the specified size and return just the - /// reference to the underlying memory. All bytes will be - /// initialized to zero. - static MemRef create_array(size_t init_size, Allocator&); - -#ifdef REALM_DEBUG - size_t blob_size() const noexcept; - void verify() const; - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - -private: - size_t calc_byte_len(size_t for_size, size_t width) const override; - size_t calc_item_count(size_t bytes, size_t width) const noexcept override; -}; - - -// Implementation: - -// Creates new array (but invalid, call init_from_ref() to init) -inline ArrayBlob::ArrayBlob(Allocator& allocator) noexcept - : Array(allocator) -{ -} - -inline bool ArrayBlob::is_null(size_t index) const noexcept -{ - return (get(index) == nullptr); -} - -inline const char* ArrayBlob::get(size_t index) const noexcept -{ - return m_data + index; -} - -inline ref_type ArrayBlob::add(const char* data, size_t data_size, bool add_zero_term) -{ - return replace(m_size, m_size, data, data_size, add_zero_term); -} - -inline void ArrayBlob::insert(size_t pos, const char* data, size_t data_size, bool add_zero_term) -{ - replace(pos, pos, data, data_size, add_zero_term); -} - -inline void ArrayBlob::erase(size_t begin, size_t end) -{ - const char* data = nullptr; - size_t data_size = 0; - replace(begin, end, data, data_size); -} - -inline const char* ArrayBlob::get(const char* header, size_t pos) noexcept -{ - const char* data = get_data_from_header(header); - return data + pos; -} - -inline void ArrayBlob::create() -{ - size_t init_size = 0; - MemRef mem = create_array(init_size, get_alloc()); // Throws - init_from_mem(mem); -} - -inline MemRef ArrayBlob::create_array(size_t init_size, Allocator& allocator) -{ - bool context_flag = false; - int_fast64_t value = 0; - return Array::create(type_Normal, context_flag, wtype_Ignore, init_size, value, allocator); // Throws -} - -inline size_t ArrayBlob::calc_byte_len(size_t for_size, size_t) const -{ - return header_size + for_size; -} - -inline size_t ArrayBlob::calc_item_count(size_t bytes, size_t) const noexcept -{ - return bytes - header_size; -} - - -} // namespace realm - -#endif // REALM_ARRAY_BLOB_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_blobs_big.hpp b/Example/Pods/Realm/include/core/realm/array_blobs_big.hpp deleted file mode 100644 index d931837..0000000 --- a/Example/Pods/Realm/include/core/realm/array_blobs_big.hpp +++ /dev/null @@ -1,218 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_BIG_BLOBS_HPP -#define REALM_ARRAY_BIG_BLOBS_HPP - -#include - -namespace realm { - - -class ArrayBigBlobs : public Array { -public: - typedef BinaryData value_type; - - explicit ArrayBigBlobs(Allocator&, bool nullable) noexcept; - - BinaryData get(size_t ndx) const noexcept; - BinaryData get_at(size_t ndx, size_t& pos) const noexcept; - void set(size_t ndx, BinaryData value, bool add_zero_term = false); - void add(BinaryData value, bool add_zero_term = false); - void insert(size_t ndx, BinaryData value, bool add_zero_term = false); - void erase(size_t ndx); - void truncate(size_t new_size); - void clear(); - void destroy(); - - size_t count(BinaryData value, bool is_string = false, size_t begin = 0, size_t end = npos) const noexcept; - size_t find_first(BinaryData value, bool is_string = false, size_t begin = 0, size_t end = npos) const noexcept; - void find_all(IntegerColumn& result, BinaryData value, bool is_string = false, size_t add_offset = 0, - size_t begin = 0, size_t end = npos); - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static BinaryData get(const char* header, size_t ndx, Allocator&) noexcept; - - ref_type bptree_leaf_insert(size_t ndx, BinaryData, bool add_zero_term, TreeInsertBase& state); - - //@{ - /// Those that return a string, discard the terminating zero from - /// the stored value. Those that accept a string argument, add a - /// terminating zero before storing the value. - StringData get_string(size_t ndx) const noexcept; - void add_string(StringData value); - void set_string(size_t ndx, StringData value); - void insert_string(size_t ndx, StringData value); - static StringData get_string(const char* header, size_t ndx, Allocator&, bool nullable) noexcept; - ref_type bptree_leaf_insert_string(size_t ndx, StringData, TreeInsertBase& state); - //@} - - /// Create a new empty big blobs array and attach this accessor to - /// it. This does not modify the parent reference information of - /// this accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(); - - /// Construct a copy of the specified slice of this big blobs - /// array using the specified target allocator. - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - -#ifdef REALM_DEBUG - void verify() const; - void to_dot(std::ostream&, bool is_strings, StringData title = StringData()) const; -#endif - -private: - bool m_nullable; -}; - - -// Implementation: - -inline ArrayBigBlobs::ArrayBigBlobs(Allocator& allocator, bool nullable) noexcept - : Array(allocator) - , m_nullable(nullable) -{ -} - -inline BinaryData ArrayBigBlobs::get(size_t ndx) const noexcept -{ - ref_type ref = get_as_ref(ndx); - if (ref == 0) - return {}; // realm::null(); - - const char* blob_header = get_alloc().translate(ref); - if (!get_context_flag_from_header(blob_header)) { - const char* value = ArrayBlob::get(blob_header, 0); - size_t blob_size = get_size_from_header(blob_header); - return BinaryData(value, blob_size); - } - return {}; -} - -inline BinaryData ArrayBigBlobs::get(const char* header, size_t ndx, Allocator& alloc) noexcept -{ - ref_type blob_ref = to_ref(Array::get(header, ndx)); - if (blob_ref == 0) - return {}; - - const char* blob_header = alloc.translate(blob_ref); - if (!get_context_flag_from_header(blob_header)) { - const char* blob_data = Array::get_data_from_header(blob_header); - size_t blob_size = Array::get_size_from_header(blob_header); - return BinaryData(blob_data, blob_size); - } - return {}; -} - -inline void ArrayBigBlobs::erase(size_t ndx) -{ - ref_type blob_ref = Array::get_as_ref(ndx); - if (blob_ref != 0) { // nothing to destroy if null - Array::destroy(blob_ref, get_alloc()); // Shallow - } - Array::erase(ndx); -} - -inline void ArrayBigBlobs::truncate(size_t new_size) -{ - Array::truncate_and_destroy_children(new_size); -} - -inline void ArrayBigBlobs::clear() -{ - Array::clear_and_destroy_children(); -} - -inline void ArrayBigBlobs::destroy() -{ - Array::destroy_deep(); -} - -inline StringData ArrayBigBlobs::get_string(size_t ndx) const noexcept -{ - BinaryData bin = get(ndx); - if (bin.is_null()) - return realm::null(); - else - return StringData(bin.data(), bin.size() - 1); // Do not include terminating zero -} - -inline void ArrayBigBlobs::set_string(size_t ndx, StringData value) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - BinaryData bin(value.data(), value.size()); - bool add_zero_term = true; - set(ndx, bin, add_zero_term); -} - -inline void ArrayBigBlobs::add_string(StringData value) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - BinaryData bin(value.data(), value.size()); - bool add_zero_term = true; - add(bin, add_zero_term); -} - -inline void ArrayBigBlobs::insert_string(size_t ndx, StringData value) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - BinaryData bin(value.data(), value.size()); - bool add_zero_term = true; - insert(ndx, bin, add_zero_term); -} - -inline StringData ArrayBigBlobs::get_string(const char* header, size_t ndx, Allocator& alloc, bool nullable) noexcept -{ - static_cast(nullable); - BinaryData bin = get(header, ndx, alloc); - REALM_ASSERT_DEBUG(!(!nullable && bin.is_null())); - if (bin.is_null()) - return realm::null(); - else - return StringData(bin.data(), bin.size() - 1); // Do not include terminating zero -} - -inline ref_type ArrayBigBlobs::bptree_leaf_insert_string(size_t ndx, StringData value, TreeInsertBase& state) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - BinaryData bin(value.data(), value.size()); - bool add_zero_term = true; - return bptree_leaf_insert(ndx, bin, add_zero_term, state); -} - -inline void ArrayBigBlobs::create() -{ - bool context_flag = true; - Array::create(type_HasRefs, context_flag); // Throws -} - -inline MemRef ArrayBigBlobs::slice(size_t offset, size_t slice_size, Allocator& target_alloc) const -{ - return slice_and_clone_children(offset, slice_size, target_alloc); -} - - -} // namespace realm - -#endif // REALM_ARRAY_BIG_BLOBS_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_direct.hpp b/Example/Pods/Realm/include/core/realm/array_direct.hpp deleted file mode 100644 index e337392..0000000 --- a/Example/Pods/Realm/include/core/realm/array_direct.hpp +++ /dev/null @@ -1,372 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_DIRECT_HPP -#define REALM_ARRAY_DIRECT_HPP - -#include -#include - -using namespace realm::util; - -// clang-format off -/* wid == 16/32 likely when accessing offsets in B tree */ -#define REALM_TEMPEX(fun, wid, arg) \ - if (wid == 16) {fun<16> arg;} \ - else if (wid == 32) {fun<32> arg;} \ - else if (wid == 0) {fun<0> arg;} \ - else if (wid == 1) {fun<1> arg;} \ - else if (wid == 2) {fun<2> arg;} \ - else if (wid == 4) {fun<4> arg;} \ - else if (wid == 8) {fun<8> arg;} \ - else if (wid == 64) {fun<64> arg;} \ - else {REALM_ASSERT_DEBUG(false); fun<0> arg;} - -#define REALM_TEMPEX2(fun, targ, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX3(fun, targ1, targ2, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX4(fun, targ1, targ2, wid, targ3, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX5(fun, targ1, targ2, targ3, targ4, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} -// clang-format on - -namespace realm { - -// Direct access methods - -template -void set_direct(char* data, size_t ndx, int_fast64_t value) noexcept -{ - if (width == 0) { - REALM_ASSERT_DEBUG(value == 0); - return; - } - else if (width == 1) { - REALM_ASSERT_DEBUG(0 <= value && value <= 0x01); - size_t byte_ndx = ndx / 8; - size_t bit_ndx = ndx % 8; - typedef unsigned char uchar; - uchar* p = reinterpret_cast(data) + byte_ndx; - *p = uchar((*p & ~(0x01 << bit_ndx)) | (int(value) & 0x01) << bit_ndx); - } - else if (width == 2) { - REALM_ASSERT_DEBUG(0 <= value && value <= 0x03); - size_t byte_ndx = ndx / 4; - size_t bit_ndx = ndx % 4 * 2; - typedef unsigned char uchar; - uchar* p = reinterpret_cast(data) + byte_ndx; - *p = uchar((*p & ~(0x03 << bit_ndx)) | (int(value) & 0x03) << bit_ndx); - } - else if (width == 4) { - REALM_ASSERT_DEBUG(0 <= value && value <= 0x0F); - size_t byte_ndx = ndx / 2; - size_t bit_ndx = ndx % 2 * 4; - typedef unsigned char uchar; - uchar* p = reinterpret_cast(data) + byte_ndx; - *p = uchar((*p & ~(0x0F << bit_ndx)) | (int(value) & 0x0F) << bit_ndx); - } - else if (width == 8) { - REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && - value <= std::numeric_limits::max()); - *(reinterpret_cast(data) + ndx) = int8_t(value); - } - else if (width == 16) { - REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && - value <= std::numeric_limits::max()); - *(reinterpret_cast(data) + ndx) = int16_t(value); - } - else if (width == 32) { - REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && - value <= std::numeric_limits::max()); - *(reinterpret_cast(data) + ndx) = int32_t(value); - } - else if (width == 64) { - REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && - value <= std::numeric_limits::max()); - *(reinterpret_cast(data) + ndx) = int64_t(value); - } - else { - REALM_ASSERT_DEBUG(false); - } -} - -template -void fill_direct(char* data, size_t begin, size_t end, int_fast64_t value) noexcept -{ - for (size_t i = begin; i != end; ++i) - set_direct(data, i, value); -} - -template -int64_t get_direct(const char* data, size_t ndx) noexcept -{ - if (w == 0) { - return 0; - } - if (w == 1) { - size_t offset = ndx >> 3; - return (data[offset] >> (ndx & 7)) & 0x01; - } - if (w == 2) { - size_t offset = ndx >> 2; - return (data[offset] >> ((ndx & 3) << 1)) & 0x03; - } - if (w == 4) { - size_t offset = ndx >> 1; - return (data[offset] >> ((ndx & 1) << 2)) & 0x0F; - } - if (w == 8) { - return *reinterpret_cast(data + ndx); - } - if (w == 16) { - size_t offset = ndx * 2; - return *reinterpret_cast(data + offset); - } - if (w == 32) { - size_t offset = ndx * 4; - return *reinterpret_cast(data + offset); - } - if (w == 64) { - size_t offset = ndx * 8; - return *reinterpret_cast(data + offset); - } - REALM_ASSERT_DEBUG(false); - return int64_t(-1); -} - -inline int64_t get_direct(const char* data, size_t width, size_t ndx) noexcept -{ - REALM_TEMPEX(return get_direct, width, (data, ndx)); -} - - -template -inline std::pair get_two(const char* data, size_t ndx) noexcept -{ - return std::make_pair(to_size_t(get_direct(data, ndx + 0)), to_size_t(get_direct(data, ndx + 1))); -} - -inline std::pair get_two(const char* data, size_t width, size_t ndx) noexcept -{ - REALM_TEMPEX(return get_two, width, (data, ndx)); -} - - -template -inline void get_three(const char* data, size_t ndx, ref_type& v0, ref_type& v1, ref_type& v2) noexcept -{ - v0 = to_ref(get_direct(data, ndx + 0)); - v1 = to_ref(get_direct(data, ndx + 1)); - v2 = to_ref(get_direct(data, ndx + 2)); -} - -inline void get_three(const char* data, size_t width, size_t ndx, ref_type& v0, ref_type& v1, ref_type& v2) noexcept -{ - REALM_TEMPEX(get_three, width, (data, ndx, v0, v1, v2)); -} - - -// Lower/upper bound in sorted sequence -// ------------------------------------ -// -// 3 3 3 4 4 4 5 6 7 9 9 9 -// ^ ^ ^ ^ ^ -// | | | | | -// | | | | -- Lower and upper bound of 15 -// | | | | -// | | | -- Lower and upper bound of 8 -// | | | -// | | -- Upper bound of 4 -// | | -// | -- Lower bound of 4 -// | -// -- Lower and upper bound of 1 -// -// These functions are semantically identical to std::lower_bound() and -// std::upper_bound(). -// -// We currently use binary search. See for example -// http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary. -template -inline size_t lower_bound(const char* data, size_t size, int64_t value) noexcept -{ - // The binary search used here is carefully optimized. Key trick is to use a single - // loop controlling variable (size) instead of high/low pair, and to keep updates - // to size done inside the loop independent of comparisons. Further key to speed - // is to avoid branching inside the loop, using conditional moves instead. This - // provides robust performance for random searches, though predictable searches - // might be slightly faster if we used branches instead. The loop unrolling yields - // a final 5-20% speedup depending on circumstances. - - size_t low = 0; - - while (size >= 8) { - // The following code (at X, Y and Z) is 3 times manually unrolled instances of (A) below. - // These code blocks must be kept in sync. Meassurements indicate 3 times unrolling to give - // the best performance. See (A) for comments on the loop body. - // (X) - size_t half = size / 2; - size_t other_half = size - half; - size_t probe = low + half; - size_t other_low = low + other_half; - int64_t v = get_direct(data, probe); - size = half; - low = (v < value) ? other_low : low; - - // (Y) - half = size / 2; - other_half = size - half; - probe = low + half; - other_low = low + other_half; - v = get_direct(data, probe); - size = half; - low = (v < value) ? other_low : low; - - // (Z) - half = size / 2; - other_half = size - half; - probe = low + half; - other_low = low + other_half; - v = get_direct(data, probe); - size = half; - low = (v < value) ? other_low : low; - } - while (size > 0) { - // (A) - // To understand the idea in this code, please note that - // for performance, computation of size for the next iteration - // MUST be INDEPENDENT of the conditional. This allows the - // processor to unroll the loop as fast as possible, and it - // minimizes the length of dependence chains leading up to branches. - // Making the unfolding of the loop independent of the data being - // searched, also minimizes the delays incurred by branch - // mispredictions, because they can be determined earlier - // and the speculation corrected earlier. - - // Counterintuitive: - // To make size independent of data, we cannot always split the - // range at the theoretical optimal point. When we determine that - // the key is larger than the probe at some index K, and prepare - // to search the upper part of the range, you would normally start - // the search at the next index, K+1, to get the shortest range. - // We can only do this when splitting a range with odd number of entries. - // If there is an even number of entries we search from K instead of K+1. - // This potentially leads to redundant comparisons, but in practice we - // gain more performance by making the changes to size predictable. - - // if size is even, half and other_half are the same. - // if size is odd, half is one less than other_half. - size_t half = size / 2; - size_t other_half = size - half; - size_t probe = low + half; - size_t other_low = low + other_half; - int64_t v = get_direct(data, probe); - size = half; - // for max performance, the line below should compile into a conditional - // move instruction. Not all compilers do this. To maximize chance - // of succes, no computation should be done in the branches of the - // conditional. - low = (v < value) ? other_low : low; - }; - - return low; -} - -// See lower_bound() -template -inline size_t upper_bound(const char* data, size_t size, int64_t value) noexcept -{ - size_t low = 0; - while (size >= 8) { - size_t half = size / 2; - size_t other_half = size - half; - size_t probe = low + half; - size_t other_low = low + other_half; - int64_t v = get_direct(data, probe); - size = half; - low = (value >= v) ? other_low : low; - - half = size / 2; - other_half = size - half; - probe = low + half; - other_low = low + other_half; - v = get_direct(data, probe); - size = half; - low = (value >= v) ? other_low : low; - - half = size / 2; - other_half = size - half; - probe = low + half; - other_low = low + other_half; - v = get_direct(data, probe); - size = half; - low = (value >= v) ? other_low : low; - } - - while (size > 0) { - size_t half = size / 2; - size_t other_half = size - half; - size_t probe = low + half; - size_t other_low = low + other_half; - int64_t v = get_direct(data, probe); - size = half; - low = (value >= v) ? other_low : low; - }; - - return low; -} -} - -#endif /* ARRAY_TPL_HPP_ */ diff --git a/Example/Pods/Realm/include/core/realm/array_integer.hpp b/Example/Pods/Realm/include/core/realm/array_integer.hpp deleted file mode 100644 index 40822a8..0000000 --- a/Example/Pods/Realm/include/core/realm/array_integer.hpp +++ /dev/null @@ -1,625 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_INTEGER_HPP -#define REALM_ARRAY_INTEGER_HPP - -#include -#include -#include - -namespace realm { - -class ArrayInteger : public Array { -public: - typedef int64_t value_type; - - explicit ArrayInteger(Allocator&) noexcept; - ~ArrayInteger() noexcept override - { - } - - void create(Type type = type_Normal, bool context_flag = false); - - void add(int64_t value); - void set(size_t ndx, int64_t value); - void set_uint(size_t ndx, uint_fast64_t value) noexcept; - int64_t get(size_t ndx) const noexcept; - uint64_t get_uint(size_t ndx) const noexcept; - static int64_t get(const char* header, size_t ndx) noexcept; - bool compare(const ArrayInteger& a) const noexcept; - - /// Add \a diff to the element at the specified index. - void adjust(size_t ndx, int_fast64_t diff); - - /// Add \a diff to all the elements in the specified index range. - void adjust(size_t begin, size_t end, int_fast64_t diff); - - /// Add signed \a diff to all elements that are greater than, or equal to \a - /// limit. - void adjust_ge(int_fast64_t limit, int_fast64_t diff); - - int64_t operator[](size_t ndx) const noexcept - { - return get(ndx); - } - int64_t front() const noexcept; - int64_t back() const noexcept; - - size_t lower_bound(int64_t value) const noexcept; - size_t upper_bound(int64_t value) const noexcept; - - std::vector to_vector() const; - -private: - template - bool minmax(size_t from, size_t to, uint64_t maxdiff, int64_t* min, int64_t* max) const; -}; - -class ArrayIntNull : public Array { -public: - using value_type = util::Optional; - - explicit ArrayIntNull(Allocator&) noexcept; - ~ArrayIntNull() noexcept override; - - /// Construct an array of the specified type and size, and return just the - /// reference to the underlying memory. All elements will be initialized to - /// the specified value. - static MemRef create_array(Type, bool context_flag, size_t size, value_type value, Allocator&); - void create(Type = type_Normal, bool context_flag = false); - - void init_from_ref(ref_type) noexcept; - void init_from_mem(MemRef) noexcept; - void init_from_parent() noexcept; - - size_t size() const noexcept; - bool is_empty() const noexcept; - - void insert(size_t ndx, value_type value); - void add(value_type value); - void set(size_t ndx, value_type value) noexcept; - value_type get(size_t ndx) const noexcept; - static value_type get(const char* header, size_t ndx) noexcept; - void get_chunk(size_t ndx, value_type res[8]) const noexcept; - void set_null(size_t ndx) noexcept; - bool is_null(size_t ndx) const noexcept; - int64_t null_value() const noexcept; - - value_type operator[](size_t ndx) const noexcept; - value_type front() const noexcept; - value_type back() const noexcept; - void erase(size_t ndx); - void erase(size_t begin, size_t end); - void truncate(size_t size); - void clear(); - void set_all_to_zero(); - - void move(size_t begin, size_t end, size_t dest_begin); - void move_backward(size_t begin, size_t end, size_t dest_end); - - size_t lower_bound(int64_t value) const noexcept; - size_t upper_bound(int64_t value) const noexcept; - - int64_t sum(size_t start = 0, size_t end = npos) const; - size_t count(int64_t value) const noexcept; - bool maximum(int64_t& result, size_t start = 0, size_t end = npos, size_t* return_ndx = nullptr) const; - bool minimum(int64_t& result, size_t start = 0, size_t end = npos, size_t* return_ndx = nullptr) const; - - bool find(int cond, Action action, value_type value, size_t start, size_t end, size_t baseindex, - QueryState* state) const; - - template - bool find(value_type value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - // This is the one installed into the m_finder slots. - template - bool find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state) const; - - template - bool find(value_type value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - // Optimized implementation for release mode - template - bool find_optimized(value_type value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const; - - // Called for each search result - template - bool find_action(size_t index, value_type value, QueryState* state, Callback callback) const; - - template - bool find_action_pattern(size_t index, uint64_t pattern, QueryState* state, Callback callback) const; - - // Wrappers for backwards compatibility and for simple use without - // setting up state initialization etc - template - size_t find_first(value_type value, size_t start = 0, size_t end = npos) const; - - void find_all(IntegerColumn* result, value_type value, size_t col_offset = 0, size_t begin = 0, - size_t end = npos) const; - - - size_t find_first(value_type value, size_t begin = 0, size_t end = npos) const; - - - // Overwrite Array::bptree_leaf_insert to correctly split nodes. - ref_type bptree_leaf_insert(size_t ndx, value_type value, TreeInsertBase& state); - - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - - /// Construct a deep copy of the specified slice of this array using the - /// specified target allocator. Subarrays will be cloned. - MemRef slice_and_clone_children(size_t offset, size_t slice_size, Allocator& target_alloc) const; - -protected: - void avoid_null_collision(int64_t value); - -private: - template - bool minmax_helper(int64_t& result, size_t start = 0, size_t end = npos, size_t* return_ndx = nullptr) const; - - int_fast64_t choose_random_null(int64_t incoming) const; - void replace_nulls_with(int64_t new_null); - bool can_use_as_null(int64_t value) const; -}; - - -// Implementation: - -inline ArrayInteger::ArrayInteger(Allocator& allocator) noexcept - : Array(allocator) -{ - m_is_inner_bptree_node = false; -} - -inline void ArrayInteger::add(int64_t value) -{ - Array::add(value); -} - -inline int64_t ArrayInteger::get(size_t ndx) const noexcept -{ - return Array::get(ndx); -} - -inline int64_t ArrayInteger::get(const char* header, size_t ndx) noexcept -{ - return Array::get(header, ndx); -} - -inline void ArrayInteger::set(size_t ndx, int64_t value) -{ - Array::set(ndx, value); -} - -inline void ArrayInteger::set_uint(size_t ndx, uint_fast64_t value) noexcept -{ - // When a value of a signed type is converted to an unsigned type, the C++ - // standard guarantees that negative values are converted from the native - // representation to 2's complement, but the effect of conversions in the - // opposite direction is left unspecified by the - // standard. `realm::util::from_twos_compl()` is used here to perform the - // correct opposite unsigned-to-signed conversion, which reduces to a no-op - // when 2's complement is the native representation of negative values. - set(ndx, util::from_twos_compl(value)); -} - -inline bool ArrayInteger::compare(const ArrayInteger& a) const noexcept -{ - if (a.size() != size()) - return false; - - for (size_t i = 0; i < size(); ++i) { - if (get(i) != a.get(i)) - return false; - } - - return true; -} - -inline int64_t ArrayInteger::front() const noexcept -{ - return Array::front(); -} - -inline int64_t ArrayInteger::back() const noexcept -{ - return Array::back(); -} - -inline void ArrayInteger::adjust(size_t ndx, int_fast64_t diff) -{ - Array::adjust(ndx, diff); -} - -inline void ArrayInteger::adjust(size_t begin, size_t end, int_fast64_t diff) -{ - Array::adjust(begin, end, diff); -} - -inline void ArrayInteger::adjust_ge(int_fast64_t limit, int_fast64_t diff) -{ - Array::adjust_ge(limit, diff); -} - -inline size_t ArrayInteger::lower_bound(int64_t value) const noexcept -{ - return lower_bound_int(value); -} - -inline size_t ArrayInteger::upper_bound(int64_t value) const noexcept -{ - return upper_bound_int(value); -} - - -inline ArrayIntNull::ArrayIntNull(Allocator& allocator) noexcept - : Array(allocator) -{ -} - -inline ArrayIntNull::~ArrayIntNull() noexcept -{ -} - -inline void ArrayIntNull::create(Type type, bool context_flag) -{ - MemRef r = create_array(type, context_flag, 0, util::none, m_alloc); - init_from_mem(r); -} - - -inline size_t ArrayIntNull::size() const noexcept -{ - return Array::size() - 1; -} - -inline bool ArrayIntNull::is_empty() const noexcept -{ - return size() == 0; -} - -inline void ArrayIntNull::insert(size_t ndx, value_type value) -{ - if (value) { - avoid_null_collision(*value); - Array::insert(ndx + 1, *value); - } - else { - Array::insert(ndx + 1, null_value()); - } -} - -inline void ArrayIntNull::add(value_type value) -{ - if (value) { - avoid_null_collision(*value); - Array::add(*value); - } - else { - Array::add(null_value()); - } -} - -inline void ArrayIntNull::set(size_t ndx, value_type value) noexcept -{ - if (value) { - avoid_null_collision(*value); - Array::set(ndx + 1, *value); - } - else { - Array::set(ndx + 1, null_value()); - } -} - -inline void ArrayIntNull::set_null(size_t ndx) noexcept -{ - Array::set(ndx + 1, null_value()); -} - -inline ArrayIntNull::value_type ArrayIntNull::get(size_t ndx) const noexcept -{ - int64_t value = Array::get(ndx + 1); - if (value == null_value()) { - return util::none; - } - return util::some(value); -} - -inline ArrayIntNull::value_type ArrayIntNull::get(const char* header, size_t ndx) noexcept -{ - int64_t null_value = Array::get(header, 0); - int64_t value = Array::get(header, ndx + 1); - if (value == null_value) { - return util::none; - } - else { - return util::some(value); - } -} - -inline bool ArrayIntNull::is_null(size_t ndx) const noexcept -{ - return !get(ndx); -} - -inline int64_t ArrayIntNull::null_value() const noexcept -{ - return Array::get(0); -} - -inline ArrayIntNull::value_type ArrayIntNull::operator[](size_t ndx) const noexcept -{ - return get(ndx); -} - -inline ArrayIntNull::value_type ArrayIntNull::front() const noexcept -{ - return get(0); -} - -inline ArrayIntNull::value_type ArrayIntNull::back() const noexcept -{ - return Array::back(); -} - -inline void ArrayIntNull::erase(size_t ndx) -{ - Array::erase(ndx + 1); -} - -inline void ArrayIntNull::erase(size_t begin, size_t end) -{ - Array::erase(begin + 1, end + 1); -} - -inline void ArrayIntNull::truncate(size_t to_size) -{ - Array::truncate(to_size + 1); -} - -inline void ArrayIntNull::clear() -{ - truncate(0); -} - -inline void ArrayIntNull::set_all_to_zero() -{ - // FIXME: Array::set_all_to_zero does something else - for (size_t i = 0; i < size(); ++i) { - set(i, 0); - } -} - -inline void ArrayIntNull::move(size_t begin, size_t end, size_t dest_begin) -{ - Array::move(begin + 1, end + 1, dest_begin + 1); -} - -inline void ArrayIntNull::move_backward(size_t begin, size_t end, size_t dest_end) -{ - Array::move_backward(begin + 1, end + 1, dest_end + 1); -} - -inline size_t ArrayIntNull::lower_bound(int64_t value) const noexcept -{ - // FIXME: Consider this behaviour with NULLs. - // Array::lower_bound_int assumes an already sorted array, but - // this array could be sorted with nulls first or last. - return Array::lower_bound_int(value); -} - -inline size_t ArrayIntNull::upper_bound(int64_t value) const noexcept -{ - // FIXME: see lower_bound - return Array::upper_bound_int(value); -} - -inline int64_t ArrayIntNull::sum(size_t start, size_t end) const -{ - // FIXME: Optimize - int64_t sum_of_range = 0; - if (end == npos) - end = size(); - for (size_t i = start; i < end; ++i) { - value_type x = get(i); - if (x) { - sum_of_range += *x; - } - } - return sum_of_range; -} - -inline size_t ArrayIntNull::count(int64_t value) const noexcept -{ - size_t count_of_value = Array::count(value); - if (value == null_value()) { - --count_of_value; - } - return count_of_value; -} - -// FIXME: Optimize -template -inline bool ArrayIntNull::minmax_helper(int64_t& result, size_t start, size_t end, size_t* return_ndx) const -{ - size_t best_index = 1; - - if (end == npos) { - end = m_size; - } - - ++start; - - REALM_ASSERT(start < m_size && end <= m_size && start < end); - - if (m_size == 1) { - // empty array - return false; - } - - if (m_width == 0) { - if (return_ndx) - *return_ndx = best_index - 1; - result = 0; - return true; - } - - int64_t m = Array::get(start); - - const int64_t null_val = null_value(); - for (; start < end; ++start) { - const int64_t v = Array::get(start); - if (find_max ? v > m : v < m) { - if (v == null_val) { - continue; - } - m = v; - best_index = start; - } - } - - result = m; - if (return_ndx) { - *return_ndx = best_index - 1; - } - return true; -} - -inline bool ArrayIntNull::maximum(int64_t& result, size_t start, size_t end, size_t* return_ndx) const -{ - return minmax_helper(result, start, end, return_ndx); -} - -inline bool ArrayIntNull::minimum(int64_t& result, size_t start, size_t end, size_t* return_ndx) const -{ - return minmax_helper(result, start, end, return_ndx); -} - -inline bool ArrayIntNull::find(int cond, Action action, value_type value, size_t start, size_t end, size_t baseindex, - QueryState* state) const -{ - if (value) { - return Array::find(cond, action, *value, start, end, baseindex, state, true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); - } - else { - return Array::find(cond, action, 0 /* unused dummy*/, start, end, baseindex, state, - true /*treat as nullable array*/, true /*search for null, ignore value argument*/); - } -} - -template -bool ArrayIntNull::find(value_type value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const -{ - if (value) { - return Array::find(*value, start, end, baseindex, state, std::forward(callback), - true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); - } - else { - return Array::find(0 /*ignored*/, start, end, baseindex, state, - std::forward(callback), true /*treat as nullable array*/, - true /*search for null, ignore value argument*/); - } -} - - -template -bool ArrayIntNull::find(int64_t value, size_t start, size_t end, size_t baseindex, QueryState* state) const -{ - return Array::find(value, start, end, baseindex, state, true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); -} - - -template -bool ArrayIntNull::find(value_type value, size_t start, size_t end, size_t baseindex, QueryState* state, - Callback callback) const -{ - if (value) { - return Array::find(*value, start, end, baseindex, state, std::forward(callback), - true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); - } - else { - return Array::find(0 /*ignored*/, start, end, baseindex, state, - std::forward(callback), true /*treat as nullable array*/, - true /*search for null, ignore value argument*/); - } -} - - -template -bool ArrayIntNull::find_action(size_t index, value_type value, QueryState* state, Callback callback) const -{ - if (value) { - return Array::find_action(index, *value, state, callback, true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); - } - else { - return Array::find_action(index, 0 /* ignored */, state, callback, - true /*treat as nullable array*/, - true /*search for null, ignore value argument*/); - } -} - - -template -bool ArrayIntNull::find_action_pattern(size_t index, uint64_t pattern, QueryState* state, - Callback callback) const -{ - return Array::find_action_pattern(index, pattern, state, callback, - true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); -} - - -template -size_t ArrayIntNull::find_first(value_type value, size_t start, size_t end) const -{ - QueryState state; - state.init(act_ReturnFirst, nullptr, 1); - if (value) { - Array::find(*value, start, end, 0, &state, Array::CallbackDummy(), - true /*treat as nullable array*/, - false /*search parameter given in 'value' argument*/); - } - else { - Array::find(0 /*ignored*/, start, end, 0, &state, Array::CallbackDummy(), - true /*treat as nullable array*/, - true /*search for null, ignore value argument*/); - } - - if (state.m_match_count > 0) - return to_size_t(state.m_state); - else - return not_found; -} - -inline size_t ArrayIntNull::find_first(value_type value, size_t begin, size_t end) const -{ - return find_first(value, begin, end); -} -} - -#endif // REALM_ARRAY_INTEGER_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_string.hpp b/Example/Pods/Realm/include/core/realm/array_string.hpp deleted file mode 100644 index bbf3203..0000000 --- a/Example/Pods/Realm/include/core/realm/array_string.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_STRING_HPP -#define REALM_ARRAY_STRING_HPP - -#include - -namespace realm { - -/* -ArrayString stores strings as a concecutive list of fixed-length blocks of m_width bytes. The -longest string it can store is (m_width - 1) bytes before it needs to expand. - -An example of the format for m_width = 4 is following sequence of bytes, where x is payload: - -xxx0 xx01 x002 0003 0004 (strings "xxx",. "xx", "x", "", realm::null()) - -So each string is 0 terminated, and the last byte in a block tells how many 0s are present, except -for a realm::null() which has the byte set to m_width (4). The byte is used to compute the length of a string -in various functions. - -New: If m_witdh = 0, then all elements are realm::null(). So to add an empty string we must expand m_width -New: StringData is null() if-and-only-if StringData::data() == 0. -*/ - -class ArrayString : public Array { -public: - static const size_t max_width = 64; - - typedef StringData value_type; - // Constructor defaults to non-nullable because we use non-nullable ArrayString so many places internally in core - // (data which isn't user payload) where null isn't needed. - explicit ArrayString(Allocator&, bool nullable = false) noexcept; - ~ArrayString() noexcept override - { - } - - bool is_null(size_t ndx) const; - void set_null(size_t ndx); - StringData get(size_t ndx) const noexcept; - void add(); - void add(StringData value); - void set(size_t ndx, StringData value); - void insert(size_t ndx, StringData value); - void erase(size_t ndx); - - size_t count(StringData value, size_t begin = 0, size_t end = npos) const noexcept; - size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const noexcept; - void find_all(IntegerColumn& result, StringData value, size_t add_offset = 0, size_t begin = 0, - size_t end = npos); - - /// Compare two string arrays for equality. - bool compare_string(const ArrayString&) const noexcept; - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static StringData get(const char* header, size_t ndx, bool nullable) noexcept; - - ref_type bptree_leaf_insert(size_t ndx, StringData, TreeInsertBase& state); - - /// Construct a string array of the specified size and return just - /// the reference to the underlying memory. All elements will be - /// initialized to the empty string. - static MemRef create_array(size_t size, Allocator&); - - /// Create a new empty string array and attach this accessor to - /// it. This does not modify the parent reference information of - /// this accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(); - - /// Construct a copy of the specified slice of this string array - /// using the specified target allocator. - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - -#ifdef REALM_DEBUG - void string_stats() const; - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - -private: - size_t calc_byte_len(size_t num_items, size_t width) const override; - size_t calc_item_count(size_t bytes, size_t width) const noexcept override; - - bool m_nullable; -}; - - -// Implementation: - -// Creates new array (but invalid, call init_from_ref() to init) -inline ArrayString::ArrayString(Allocator& allocator, bool nullable) noexcept - : Array(allocator) - , m_nullable(nullable) -{ -} - -inline void ArrayString::create() -{ - size_t init_size = 0; - MemRef mem = create_array(init_size, get_alloc()); // Throws - init_from_mem(mem); -} - -inline MemRef ArrayString::create_array(size_t init_size, Allocator& allocator) -{ - bool context_flag = false; - int_fast64_t value = 0; - return Array::create(type_Normal, context_flag, wtype_Multiply, init_size, value, allocator); // Throws -} - -inline StringData ArrayString::get(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_size); - if (m_width == 0) - return m_nullable ? realm::null() : StringData(""); - - const char* data = m_data + (ndx * m_width); - size_t array_size = (m_width - 1) - data[m_width - 1]; - - if (array_size == static_cast(-1)) - return m_nullable ? realm::null() : StringData(""); - - REALM_ASSERT_EX(data[array_size] == 0, data[array_size], - array_size); // Realm guarantees 0 terminated return strings - return StringData(data, array_size); -} - -inline void ArrayString::add(StringData value) -{ - REALM_ASSERT(!(!m_nullable && value.is_null())); - insert(m_size, value); // Throws -} - -inline void ArrayString::add() -{ - add(m_nullable ? realm::null() : StringData("")); // Throws -} - -inline StringData ArrayString::get(const char* header, size_t ndx, bool nullable) noexcept -{ - REALM_ASSERT(ndx < get_size_from_header(header)); - uint_least8_t width = get_width_from_header(header); - const char* data = get_data_from_header(header) + (ndx * width); - - if (width == 0) - return nullable ? realm::null() : StringData(""); - - size_t size = (width - 1) - data[width - 1]; - - if (size == static_cast(-1)) - return nullable ? realm::null() : StringData(""); - - return StringData(data, size); -} - - -} // namespace realm - -#endif // REALM_ARRAY_STRING_HPP diff --git a/Example/Pods/Realm/include/core/realm/array_string_long.hpp b/Example/Pods/Realm/include/core/realm/array_string_long.hpp deleted file mode 100644 index af9911e..0000000 --- a/Example/Pods/Realm/include/core/realm/array_string_long.hpp +++ /dev/null @@ -1,224 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_STRING_LONG_HPP -#define REALM_ARRAY_STRING_LONG_HPP - -#include -#include - -namespace realm { - - -class ArrayStringLong : public Array { -public: - typedef StringData value_type; - - explicit ArrayStringLong(Allocator&, bool nullable) noexcept; - ~ArrayStringLong() noexcept override - { - } - - /// Create a new empty long string array and attach this accessor to - /// it. This does not modify the parent reference information of - /// this accessor. - /// - /// Note that the caller assumes ownership of the allocated - /// underlying node. It is not owned by the accessor. - void create(); - - //@{ - /// Overriding functions of Array - void init_from_ref(ref_type) noexcept; - void init_from_mem(MemRef) noexcept; - void init_from_parent() noexcept; - //@} - - bool is_empty() const noexcept; - size_t size() const noexcept; - - StringData get(size_t ndx) const noexcept; - - - void add(StringData value); - void set(size_t ndx, StringData value); - void insert(size_t ndx, StringData value); - void erase(size_t ndx); - void truncate(size_t size); - void clear(); - void destroy(); - - bool is_null(size_t ndx) const; - void set_null(size_t ndx); - - size_t count(StringData value, size_t begin = 0, size_t end = npos) const noexcept; - size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const noexcept; - void find_all(IntegerColumn& result, StringData value, size_t add_offset = 0, size_t begin = 0, - size_t end = npos) const; - - /// Get the specified element without the cost of constructing an - /// array instance. If an array instance is already available, or - /// you need to get multiple values, then this method will be - /// slower. - static StringData get(const char* header, size_t ndx, Allocator&, bool nullable) noexcept; - - ref_type bptree_leaf_insert(size_t ndx, StringData, TreeInsertBase&); - - static size_t get_size_from_header(const char*, Allocator&) noexcept; - - /// Construct a long string array of the specified size and return - /// just the reference to the underlying memory. All elements will - /// be initialized to zero size blobs. - static MemRef create_array(size_t size, Allocator&, bool nullable); - - /// Construct a copy of the specified slice of this long string - /// array using the specified target allocator. - MemRef slice(size_t offset, size_t slice_size, Allocator& target_alloc) const; - -#ifdef REALM_DEBUG - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - - bool update_from_parent(size_t old_baseline) noexcept; - -private: - ArrayInteger m_offsets; - ArrayBlob m_blob; - Array m_nulls; - bool m_nullable; -}; - - -// Implementation: -inline ArrayStringLong::ArrayStringLong(Allocator& allocator, bool nullable) noexcept - : Array(allocator) - , m_offsets(allocator) - , m_blob(allocator) - , m_nulls(nullable ? allocator : Allocator::get_default()) - , m_nullable(nullable) -{ - m_offsets.set_parent(this, 0); - m_blob.set_parent(this, 1); - if (nullable) - m_nulls.set_parent(this, 2); -} - -inline void ArrayStringLong::create() -{ - size_t init_size = 0; - MemRef mem = create_array(init_size, get_alloc(), m_nullable); // Throws - init_from_mem(mem); -} - -inline void ArrayStringLong::init_from_ref(ref_type ref) noexcept -{ - REALM_ASSERT(ref); - char* header = get_alloc().translate(ref); - init_from_mem(MemRef(header, ref, m_alloc)); - m_nullable = (Array::size() == 3); -} - -inline void ArrayStringLong::init_from_parent() noexcept -{ - ref_type ref = get_ref_from_parent(); - init_from_ref(ref); -} - -inline bool ArrayStringLong::is_empty() const noexcept -{ - return m_offsets.is_empty(); -} - -inline size_t ArrayStringLong::size() const noexcept -{ - return m_offsets.size(); -} - -inline StringData ArrayStringLong::get(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_offsets.size()); - - if (m_nullable && m_nulls.get(ndx) == 0) - return realm::null(); - - size_t begin, end; - if (0 < ndx) { - begin = to_size_t(m_offsets.get(ndx - 1)); - end = to_size_t(m_offsets.get(ndx)); - } - else { - begin = 0; - end = to_size_t(m_offsets.get(0)); - } - --end; // Discount the terminating zero - - return StringData(m_blob.get(begin), end - begin); -} - -inline void ArrayStringLong::truncate(size_t new_size) -{ - REALM_ASSERT_3(new_size, <, m_offsets.size()); - - size_t blob_size = new_size ? to_size_t(m_offsets.get(new_size - 1)) : 0; - - m_offsets.truncate(new_size); - m_blob.truncate(blob_size); - if (m_nullable) - m_nulls.truncate(new_size); -} - -inline void ArrayStringLong::clear() -{ - m_blob.clear(); - m_offsets.clear(); - if (m_nullable) - m_nulls.clear(); -} - -inline void ArrayStringLong::destroy() -{ - m_blob.destroy(); - m_offsets.destroy(); - if (m_nullable) - m_nulls.destroy(); - Array::destroy(); -} - -inline bool ArrayStringLong::update_from_parent(size_t old_baseline) noexcept -{ - bool res = Array::update_from_parent(old_baseline); - if (res) { - m_blob.update_from_parent(old_baseline); - m_offsets.update_from_parent(old_baseline); - if (m_nullable) - m_nulls.update_from_parent(old_baseline); - } - return res; -} - -inline size_t ArrayStringLong::get_size_from_header(const char* header, Allocator& alloc) noexcept -{ - ref_type offsets_ref = to_ref(Array::get(header, 0)); - const char* offsets_header = alloc.translate(offsets_ref); - return Array::get_size_from_header(offsets_header); -} - - -} // namespace realm - -#endif // REALM_ARRAY_STRING_LONG_HPP diff --git a/Example/Pods/Realm/include/core/realm/binary_data.hpp b/Example/Pods/Realm/include/core/realm/binary_data.hpp deleted file mode 100644 index cc1c283..0000000 --- a/Example/Pods/Realm/include/core/realm/binary_data.hpp +++ /dev/null @@ -1,235 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_BINARY_DATA_HPP -#define REALM_BINARY_DATA_HPP - -#include -#include -#include -#include - -#include -#include -#include - -namespace realm { - -/// A reference to a chunk of binary data. -/// -/// This class does not own the referenced memory, nor does it in any other way -/// attempt to manage the lifetime of it. -/// -/// \sa StringData -class BinaryData { -public: - BinaryData() noexcept - : m_data(nullptr) - , m_size(0) - { - } - BinaryData(const char* external_data, size_t data_size) noexcept - : m_data(external_data) - , m_size(data_size) - { - } - template - explicit BinaryData(const char (&external_data)[N]) - : m_data(external_data) - , m_size(N) - { - } - template - explicit BinaryData(const std::basic_string&); - - template - explicit operator std::basic_string() const; - - char operator[](size_t i) const noexcept - { - return m_data[i]; - } - - const char* data() const noexcept - { - return m_data; - } - size_t size() const noexcept - { - return m_size; - } - - /// Is this a null reference? - /// - /// An instance of BinaryData is a null reference when, and only when the - /// stored size is zero (size()) and the stored pointer is the null pointer - /// (data()). - /// - /// In the case of the empty byte sequence, the stored size is still zero, - /// but the stored pointer is **not** the null pointer. Note that the actual - /// value of the pointer is immaterial in this case (as long as it is not - /// zero), because when the size is zero, it is an error to dereference the - /// pointer. - /// - /// Conversion of a BinaryData object to `bool` yields the logical negation - /// of the result of calling this function. In other words, a BinaryData - /// object is converted to true if it is not the null reference, otherwise - /// it is converted to false. - /// - /// It is important to understand that all of the functions and operators in - /// this class, and most of the functions in the Realm API in general - /// makes no distinction between a null reference and a reference to the - /// empty byte sequence. These functions and operators never look at the - /// stored pointer if the stored size is zero. - bool is_null() const noexcept; - - friend bool operator==(const BinaryData&, const BinaryData&) noexcept; - friend bool operator!=(const BinaryData&, const BinaryData&) noexcept; - - //@{ - /// Trivial bytewise lexicographical comparison. - friend bool operator<(const BinaryData&, const BinaryData&) noexcept; - friend bool operator>(const BinaryData&, const BinaryData&) noexcept; - friend bool operator<=(const BinaryData&, const BinaryData&) noexcept; - friend bool operator>=(const BinaryData&, const BinaryData&) noexcept; - //@} - - bool begins_with(BinaryData) const noexcept; - bool ends_with(BinaryData) const noexcept; - bool contains(BinaryData) const noexcept; - - template - friend std::basic_ostream& operator<<(std::basic_ostream&, const BinaryData&); - - explicit operator bool() const noexcept; - -private: - const char* m_data; - size_t m_size; -}; - -/// A read-only chunk of binary data. -class OwnedBinaryData : public OwnedData { -public: - using OwnedData::OwnedData; - - OwnedBinaryData() = default; - OwnedBinaryData(const BinaryData& binary_data) - : OwnedData(binary_data.data(), binary_data.size()) - { - } - - BinaryData get() const - { - return {data(), size()}; - } -}; - - -// Implementation: - -template -inline BinaryData::BinaryData(const std::basic_string& s) - : m_data(s.data()) - , m_size(s.size()) -{ -} - -template -inline BinaryData::operator std::basic_string() const -{ - return std::basic_string(m_data, m_size); -} - -inline bool BinaryData::is_null() const noexcept -{ - return !m_data; -} - -inline bool operator==(const BinaryData& a, const BinaryData& b) noexcept -{ - return a.m_size == b.m_size && a.is_null() == b.is_null() && safe_equal(a.m_data, a.m_data + a.m_size, b.m_data); -} - -inline bool operator!=(const BinaryData& a, const BinaryData& b) noexcept -{ - return !(a == b); -} - -inline bool operator<(const BinaryData& a, const BinaryData& b) noexcept -{ - if (a.is_null() || b.is_null()) - return !a.is_null() < !b.is_null(); - - return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, b.m_data, b.m_data + b.m_size); -} - -inline bool operator>(const BinaryData& a, const BinaryData& b) noexcept -{ - return b < a; -} - -inline bool operator<=(const BinaryData& a, const BinaryData& b) noexcept -{ - return !(b < a); -} - -inline bool operator>=(const BinaryData& a, const BinaryData& b) noexcept -{ - return !(a < b); -} - -inline bool BinaryData::begins_with(BinaryData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - - return d.m_size <= m_size && safe_equal(m_data, m_data + d.m_size, d.m_data); -} - -inline bool BinaryData::ends_with(BinaryData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - - return d.m_size <= m_size && safe_equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data); -} - -inline bool BinaryData::contains(BinaryData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - - return d.m_size == 0 || std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size; -} - -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const BinaryData& d) -{ - out << "BinaryData(" << static_cast(d.m_data) << ", " << d.m_size << ")"; - return out; -} - -inline BinaryData::operator bool() const noexcept -{ - return !is_null(); -} - -} // namespace realm - -#endif // REALM_BINARY_DATA_HPP diff --git a/Example/Pods/Realm/include/core/realm/bptree.hpp b/Example/Pods/Realm/include/core/realm/bptree.hpp deleted file mode 100644 index 7a5195e..0000000 --- a/Example/Pods/Realm/include/core/realm/bptree.hpp +++ /dev/null @@ -1,1262 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_BPTREE_HPP -#define REALM_BPTREE_HPP - -#include // std::unique_ptr -#include -#include -#include -#include -#include - -namespace realm { - -/// Specialize BpTree to implement column types. -template -class BpTree; - -class ArrayInteger; -class ArrayIntNull; - -class BpTreeNode : public Array { -public: - using Array::Array; - /// Get the number of elements in the B+-tree rooted at this array - /// node. The root must not be a leaf. - /// - /// Please avoid using this function (consider it deprecated). It - /// will have to be removed if we choose to get rid of the last - /// element of the main array of an inner B+-tree node that stores - /// the total number of elements in the subtree. The motivation - /// for removing it, is that it will significantly improve the - /// efficiency when inserting after, and erasing the last element. - size_t get_bptree_size() const noexcept; - - /// The root must not be a leaf. - static size_t get_bptree_size_from_header(const char* root_header) noexcept; - - - /// Find the leaf node corresponding to the specified element - /// index index. The specified element index must refer to an - /// element that exists in the tree. This function must be called - /// on an inner B+-tree node, never a leaf. Note that according to - /// invar:bptree-nonempty-inner and invar:bptree-nonempty-leaf, an - /// inner B+-tree node can never be empty. - /// - /// This function is not obliged to instantiate intermediate array - /// accessors. For this reason, this function cannot be used for - /// operations that modify the tree, as that requires an unbroken - /// chain of parent array accessors between the root and the - /// leaf. Thus, despite the fact that the returned MemRef object - /// appears to allow modification of the referenced memory, the - /// caller must handle the memory reference as if it was - /// const-qualified. - /// - /// \return (`leaf_header`, `ndx_in_leaf`) where `leaf_header` - /// points to the the header of the located leaf, and - /// `ndx_in_leaf` is the local index within that leaf - /// corresponding to the specified element index. - std::pair get_bptree_leaf(size_t elem_ndx) const noexcept; - - - class NodeInfo; - class VisitHandler; - - /// Visit leaves of the B+-tree rooted at this inner node, - /// starting with the leaf that contains the element at the - /// specified element index start offset, and ending when the - /// handler returns false. The specified element index offset must - /// refer to an element that exists in the tree. This function - /// must be called on an inner B+-tree node, never a leaf. Note - /// that according to invar:bptree-nonempty-inner and - /// invar:bptree-nonempty-leaf, an inner B+-tree node can never be - /// empty. - /// - /// \param elem_ndx_offset The start position (must be valid). - /// - /// \param elems_in_tree The total number of elements in the tree. - /// - /// \param handler The callback which will get called for each leaf. - /// - /// \return True if, and only if the handler has returned true for - /// all visited leafs. - bool visit_bptree_leaves(size_t elem_ndx_offset, size_t elems_in_tree, VisitHandler& handler); - - - class UpdateHandler; - - /// Call the handler for every leaf. This function must be called - /// on an inner B+-tree node, never a leaf. - void update_bptree_leaves(UpdateHandler&); - - /// Call the handler for the leaf that contains the element at the - /// specified index. This function must be called on an inner - /// B+-tree node, never a leaf. - void update_bptree_elem(size_t elem_ndx, UpdateHandler&); - - - class EraseHandler; - - /// Erase the element at the specified index in the B+-tree with - /// the specified root. When erasing the last element, you must - /// pass npos in place of the index. This function must be called - /// with a root that is an inner B+-tree node, never a leaf. - /// - /// This function is guaranteed to succeed (not throw) if the - /// specified element was inserted during the current transaction, - /// and no other modifying operation has been carried out since - /// then (noexcept:bptree-erase-alt). - /// - /// FIXME: ExceptionSafety: The exception guarantee explained - /// above is not as powerfull as we would like it to be. Here is - /// what we would like: This function is guaranteed to succeed - /// (not throw) if the specified element was inserted during the - /// current transaction (noexcept:bptree-erase). This must be true - /// even if the element is modified after insertion, and/or if - /// other elements are inserted or erased around it. There are two - /// aspects of the current design that stand in the way of this - /// guarantee: (A) The fact that the node accessor, that is cached - /// in the column accessor, has to be reallocated/reinstantiated - /// when the root switches between being a leaf and an inner - /// node. This problem would go away if we always cached the last - /// used leaf accessor in the column accessor instead. (B) The - /// fact that replacing one child ref with another can fail, - /// because it may require reallocation of memory to expand the - /// bit-width. This can be fixed in two ways: Either have the - /// inner B+-tree nodes always have a bit-width of 64, or allow - /// the root node to be discarded and the column ref to be set to - /// zero in Table::m_columns. - static void erase_bptree_elem(BpTreeNode* root, size_t elem_ndx, EraseHandler&); - - template - struct TreeInsert : TreeInsertBase { - typename TreeTraits::value_type m_value; - bool m_nullable; - }; - - /// Same as bptree_insert() but insert after the last element. - template - ref_type bptree_append(TreeInsert& state); - - /// Insert an element into the B+-subtree rooted at this array - /// node. The element is inserted before the specified element - /// index. This function must be called on an inner B+-tree node, - /// never a leaf. If this inner node had to be split, this - /// function returns the `ref` of the new sibling. - template - ref_type bptree_insert(size_t elem_ndx, TreeInsert& state); - -protected: - /// Insert a new child after original. If the parent has to be - /// split, this function returns the `ref` of the new parent node. - ref_type insert_bptree_child(Array& offsets, size_t orig_child_ndx, ref_type new_sibling_ref, - TreeInsertBase& state); - - void ensure_bptree_offsets(Array& offsets); - void create_bptree_offsets(Array& offsets, int_fast64_t first_value); - - bool do_erase_bptree_elem(size_t elem_ndx, EraseHandler&); -}; - -class BpTreeBase { -public: - struct unattached_tag { - }; - - // Accessor concept: - Allocator& get_alloc() const noexcept; - void destroy() noexcept; - void detach(); - bool is_attached() const noexcept; - void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept; - size_t get_ndx_in_parent() const noexcept; - void set_ndx_in_parent(size_t ndx) noexcept; - void update_from_parent(size_t old_baseline) noexcept; - MemRef clone_deep(Allocator& alloc) const; - - // BpTree interface: - const Array& root() const noexcept; - Array& root() noexcept; - bool root_is_leaf() const noexcept; - BpTreeNode& root_as_node(); - const BpTreeNode& root_as_node() const; - void introduce_new_root(ref_type new_sibling_ref, TreeInsertBase& state, bool is_append); - void replace_root(std::unique_ptr leaf); - -protected: - explicit BpTreeBase(std::unique_ptr root); - explicit BpTreeBase(BpTreeBase&&) = default; - BpTreeBase& operator=(BpTreeBase&&) = default; - std::unique_ptr m_root; - - struct SliceHandler { - virtual MemRef slice_leaf(MemRef leaf_mem, size_t offset, size_t size, Allocator& target_alloc) = 0; - ~SliceHandler() noexcept - { - } - }; - static ref_type write_subtree(const BpTreeNode& root, size_t slice_offset, size_t slice_size, size_t table_size, - SliceHandler&, _impl::OutputStream&); - friend class ColumnBase; - friend class ColumnBaseSimple; - -private: - struct WriteSliceHandler; - - // FIXME: Move B+Tree functionality from Array to this class. -}; - - -// Default implementation of BpTree. This should work for all types that have monomorphic -// leaves (i.e. all leaves are of the same type). -template -class BpTree : public BpTreeBase { -public: - using value_type = T; - using LeafType = typename ColumnTypeTraits::leaf_type; - - /// LeafInfo is used by get_leaf() to provide access to a leaf - /// without instantiating unnecessary nodes along the way. - /// Upon return, out_leaf with hold a pointer to the leaf containing - /// the index given to get_leaf(). If the index happens to be - /// in the root node (i.e., the root is a leaf), it will point - /// to the root node. - /// If the index isn't in the root node, fallback will be initialized - /// to represent the leaf holding the node, and out_leaf will be set - /// to point to fallback. - struct LeafInfo { - const LeafType** out_leaf; - LeafType* fallback; - }; - - BpTree(); - explicit BpTree(BpTreeBase::unattached_tag); - explicit BpTree(Allocator& alloc); - REALM_DEPRECATED("Initialize with MemRef instead") explicit BpTree(std::unique_ptr init_root) - : BpTreeBase(std::move(init_root)) - { - - } - explicit BpTree(Allocator& alloc, MemRef mem) - : BpTreeBase(std::unique_ptr(new LeafType(alloc))) - { - init_from_mem(alloc, mem); - } - BpTree(BpTree&&) = default; - BpTree& operator=(BpTree&&) = default; - void init_from_ref(Allocator& alloc, ref_type ref); - void init_from_mem(Allocator& alloc, MemRef mem); - void init_from_parent(); - - size_t size() const noexcept; - bool is_empty() const noexcept - { - return size() == 0; - } - - T get(size_t ndx) const noexcept; - bool is_null(size_t ndx) const noexcept; - void set(size_t, T value); - void set_null(size_t); - void insert(size_t ndx, T value, size_t num_rows = 1); - void erase(size_t ndx, bool is_last = false); - void move_last_over(size_t ndx, size_t last_row_ndx); - void clear(); - T front() const noexcept; - T back() const noexcept; - - size_t find_first(T value, size_t begin = 0, size_t end = npos) const; - void find_all(IntegerColumn& out_indices, T value, size_t begin = 0, size_t end = npos) const; - - static MemRef create_leaf(Array::Type leaf_type, size_t size, T value, Allocator&); - - /// See LeafInfo for information about what to put in the inout_leaf - /// parameter. - /// - /// This function cannot be used for modifying operations as it - /// does not ensure the presence of an unbroken chain of parent - /// accessors. For this reason, the identified leaf should always - /// be accessed through the returned const-qualified reference, - /// and never directly through the specfied fallback accessor. - void get_leaf(size_t ndx, size_t& out_ndx_in_leaf, LeafInfo& inout_leaf) const noexcept; - - void update_each(BpTreeNode::UpdateHandler&); - void update_elem(size_t, BpTreeNode::UpdateHandler&); - - void adjust(size_t ndx, T diff); - void adjust(T diff); - void adjust_ge(T limit, T diff); - - ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream& out) const; - -#if defined(REALM_DEBUG) - void verify() const; - static size_t verify_leaf(MemRef mem, Allocator& alloc); -#endif - static void leaf_to_dot(MemRef mem, ArrayParent* parent, size_t ndx_in_parent, std::ostream& out, - Allocator& alloc); - -private: - LeafType& root_as_leaf(); - const LeafType& root_as_leaf() const; - - std::unique_ptr create_root_from_ref(Allocator& alloc, ref_type ref); - std::unique_ptr create_root_from_mem(Allocator& alloc, MemRef mem); - - struct EraseHandler; - struct UpdateHandler; - struct SetNullHandler; - struct SliceHandler; - struct AdjustHandler; - struct AdjustGEHandler; - - struct LeafValueInserter; - struct LeafNullInserter; - - template - void bptree_insert(size_t row_ndx, BpTreeNode::TreeInsert& state, size_t num_rows); -}; - - -class BpTreeNode::NodeInfo { -public: - MemRef m_mem; - Array* m_parent; - size_t m_ndx_in_parent; - size_t m_offset, m_size; -}; - -class BpTreeNode::VisitHandler { -public: - virtual bool visit(const NodeInfo& leaf_info) = 0; - virtual ~VisitHandler() noexcept - { - } -}; - - -class BpTreeNode::UpdateHandler { -public: - virtual void update(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; - virtual ~UpdateHandler() noexcept - { - } -}; - - -class BpTreeNode::EraseHandler { -public: - /// If the specified leaf has more than one element, this function - /// must erase the specified element from the leaf and return - /// false. Otherwise, when the leaf has a single element, this - /// function must return true without modifying the leaf. If \a - /// elem_ndx_in_leaf is `npos`, it refers to the last element in - /// the leaf. The implementation of this function must be - /// exception safe. This function is guaranteed to be called at - /// most once during each execution of Array::erase_bptree_elem(), - /// and *exactly* once during each *successful* execution of - /// Array::erase_bptree_elem(). - virtual bool erase_leaf_elem(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; - - virtual void destroy_leaf(MemRef leaf_mem) noexcept = 0; - - /// Must replace the current root with the specified leaf. The - /// implementation of this function must not destroy the - /// underlying root node, or any of its children, as that will be - /// done by Array::erase_bptree_elem(). The implementation of this - /// function must be exception safe. - virtual void replace_root_by_leaf(MemRef leaf_mem) = 0; - - /// Same as replace_root_by_leaf(), but must replace the root with - /// an empty leaf. Also, if this function is called during an - /// execution of Array::erase_bptree_elem(), it is guaranteed that - /// it will be preceeded by a call to erase_leaf_elem(). - virtual void replace_root_by_empty_leaf() = 0; - - virtual ~EraseHandler() noexcept - { - } -}; - - -/// Implementation: - -inline BpTreeBase::BpTreeBase(std::unique_ptr init_root) - : m_root(std::move(init_root)) -{ -} - -inline Allocator& BpTreeBase::get_alloc() const noexcept -{ - return m_root->get_alloc(); -} - -inline void BpTreeBase::destroy() noexcept -{ - if (m_root) - m_root->destroy_deep(); -} - -inline void BpTreeBase::detach() -{ - m_root->detach(); -} - -inline bool BpTreeBase::is_attached() const noexcept -{ - return m_root->is_attached(); -} - -inline bool BpTreeBase::root_is_leaf() const noexcept -{ - return !m_root->is_inner_bptree_node(); -} - -inline BpTreeNode& BpTreeBase::root_as_node() -{ - REALM_ASSERT_DEBUG(!root_is_leaf()); - REALM_ASSERT_DEBUG(dynamic_cast(m_root.get()) != nullptr); - return static_cast(root()); -} - -inline const BpTreeNode& BpTreeBase::root_as_node() const -{ - Array* arr = m_root.get(); - REALM_ASSERT_DEBUG(!root_is_leaf()); - REALM_ASSERT_DEBUG(dynamic_cast(arr) != nullptr); - return static_cast(*arr); -} - -inline void BpTreeBase::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept -{ - m_root->set_parent(parent, ndx_in_parent); -} - -inline size_t BpTreeBase::get_ndx_in_parent() const noexcept -{ - return m_root->get_ndx_in_parent(); -} - -inline void BpTreeBase::set_ndx_in_parent(size_t ndx) noexcept -{ - m_root->set_ndx_in_parent(ndx); -} - -inline void BpTreeBase::update_from_parent(size_t old_baseline) noexcept -{ - m_root->update_from_parent(old_baseline); -} - -inline MemRef BpTreeBase::clone_deep(Allocator& alloc) const -{ - return m_root->clone_deep(alloc); -} - -inline const Array& BpTreeBase::root() const noexcept -{ - return *m_root; -} - -inline Array& BpTreeBase::root() noexcept -{ - return *m_root; -} - -inline size_t BpTreeNode::get_bptree_size() const noexcept -{ - REALM_ASSERT_DEBUG(is_inner_bptree_node()); - int_fast64_t v = back(); - return size_t(v / 2); // v = 1 + 2*total_elems_in_tree -} - -inline size_t BpTreeNode::get_bptree_size_from_header(const char* root_header) noexcept -{ - REALM_ASSERT_DEBUG(get_is_inner_bptree_node_from_header(root_header)); - size_t root_size = get_size_from_header(root_header); - int_fast64_t v = get(root_header, root_size - 1); - return size_t(v / 2); // v = 1 + 2*total_elems_in_tree -} - -inline void BpTreeNode::ensure_bptree_offsets(Array& offsets) -{ - int_fast64_t first_value = get(0); - if (first_value % 2 == 0) { - offsets.init_from_ref(to_ref(first_value)); - } - else { - create_bptree_offsets(offsets, first_value); // Throws - } - offsets.set_parent(this, 0); -} - - -template -ref_type BpTreeNode::bptree_append(TreeInsert& state) -{ - // FIXME: Consider exception safety. Especially, how can the split - // be carried out in an exception safe manner? - // - // Can split be done as a separate preparation step, such that if - // the actual insert fails, the split will still have occured. - // - // Unfortunately, it requires a rather significant rearrangement - // of the insertion flow. Instead of returning the sibling ref - // from insert functions, the leaf-insert functions must instead - // call the special bptree_insert() function on the parent, which - // will then cascade the split towards the root as required. - // - // At each level where a split is required (starting at the leaf): - // - // 1. Create the new sibling. - // - // 2. Copy relevant entries over such that new sibling is in - // its final state. - // - // 3. Call Array::bptree_insert() on parent with sibling ref. - // - // 4. Rearrange entries in original sibling and truncate as - // required (must not throw). - // - // What about the 'offsets' array? It will always be - // present. Consider this carefully. - - REALM_ASSERT_DEBUG(size() >= 1 + 1 + 1); // At least one child - - ArrayParent& childs_parent = *this; - size_t child_ref_ndx = size() - 2; - ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; - char* child_header = static_cast(m_alloc.translate(child_ref)); - - bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); - if (child_is_leaf) { - size_t elem_ndx_in_child = npos; // Append - new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, - child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws - } - else { - BpTreeNode child(m_alloc); - child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); - child.set_parent(&childs_parent, child_ref_ndx); - new_sibling_ref = child.bptree_append(state); // Throws - } - - if (REALM_LIKELY(!new_sibling_ref)) { - // +2 because stored value is 1 + 2*total_elems_in_subtree - adjust(size() - 1, +2); // Throws - return 0; // Child was not split, so parent was not split either - } - - Array offsets(m_alloc); - int_fast64_t first_value = get(0); - if (first_value % 2 == 0) { - // Offsets array is present (general form) - offsets.init_from_ref(to_ref(first_value)); - offsets.set_parent(this, 0); - } - size_t child_ndx = child_ref_ndx - 1; - return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws -} - - -template -ref_type BpTreeNode::bptree_insert(size_t elem_ndx, TreeInsert& state) -{ - REALM_ASSERT_3(size(), >=, 1 + 1 + 1); // At least one child - - // Conversion to general form if in compact form. Since this - // conversion will occur from root to leaf, it will maintain - // invar:bptree-node-form. - Array offsets(m_alloc); - ensure_bptree_offsets(offsets); // Throws - - size_t child_ndx, elem_ndx_in_child; - if (elem_ndx == 0) { - // Optimization for prepend - child_ndx = 0; - elem_ndx_in_child = 0; - } - else { - // There is a choice to be made when the element is to be - // inserted between two subtrees. It can either be appended to - // the first subtree, or it can be prepended to the second - // one. We currently always append to the first subtree. It is - // essentially a matter of using the lower vs. the upper bound - // when searching through the offsets array. - child_ndx = offsets.lower_bound_int(elem_ndx); - REALM_ASSERT_3(child_ndx, <, size() - 2); - size_t elem_ndx_offset = child_ndx == 0 ? 0 : to_size_t(offsets.get(child_ndx - 1)); - elem_ndx_in_child = elem_ndx - elem_ndx_offset; - } - - ArrayParent& childs_parent = *this; - size_t child_ref_ndx = child_ndx + 1; - ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; - char* child_header = static_cast(m_alloc.translate(child_ref)); - bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); - if (child_is_leaf) { - REALM_ASSERT_3(elem_ndx_in_child, <=, REALM_MAX_BPNODE_SIZE); - new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, - child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws - } - else { - BpTreeNode child(m_alloc); - child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); - child.set_parent(&childs_parent, child_ref_ndx); - new_sibling_ref = child.bptree_insert(elem_ndx_in_child, state); // Throws - } - - if (REALM_LIKELY(!new_sibling_ref)) { - // +2 because stored value is 1 + 2*total_elems_in_subtree - adjust(size() - 1, +2); // Throws - offsets.adjust(child_ndx, offsets.size(), +1); - return 0; // Child was not split, so parent was not split either - } - - return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws -} - -template -BpTree::BpTree() - : BpTree(Allocator::get_default()) -{ -} - -template -BpTree::BpTree(Allocator& alloc) - : BpTreeBase(std::unique_ptr(new LeafType(alloc))) -{ -} - -template -BpTree::BpTree(BpTreeBase::unattached_tag) - : BpTreeBase(nullptr) -{ -} - -template -std::unique_ptr BpTree::create_root_from_mem(Allocator& alloc, MemRef mem) -{ - const char* header = mem.get_addr(); - std::unique_ptr new_root; - bool is_inner_bptree_node = Array::get_is_inner_bptree_node_from_header(header); - - bool can_reuse_root_accessor = - m_root && &m_root->get_alloc() == &alloc && m_root->is_inner_bptree_node() == is_inner_bptree_node; - if (can_reuse_root_accessor) { - if (is_inner_bptree_node) { - m_root->init_from_mem(mem); - } - else { - static_cast(*m_root).init_from_mem(mem); - } - return std::move(m_root); // Same root will be reinstalled. - } - - // Not reusing root note, allocating a new one. - if (is_inner_bptree_node) { - new_root.reset(new BpTreeNode{alloc}); - new_root->init_from_mem(mem); - } - else { - std::unique_ptr leaf{new LeafType{alloc}}; - leaf->init_from_mem(mem); - new_root = std::move(leaf); - } - return new_root; -} - -template -std::unique_ptr BpTree::create_root_from_ref(Allocator& alloc, ref_type ref) -{ - MemRef mem = MemRef{alloc.translate(ref), ref, alloc}; - return create_root_from_mem(alloc, mem); -} - -template -void BpTree::init_from_ref(Allocator& alloc, ref_type ref) -{ - auto new_root = create_root_from_ref(alloc, ref); - replace_root(std::move(new_root)); -} - -template -void BpTree::init_from_mem(Allocator& alloc, MemRef mem) -{ - auto new_root = create_root_from_mem(alloc, mem); - replace_root(std::move(new_root)); -} - -template -void BpTree::init_from_parent() -{ - ref_type ref = root().get_ref_from_parent(); - if (ref) { - ArrayParent* parent = m_root->get_parent(); - size_t ndx_in_parent = m_root->get_ndx_in_parent(); - auto new_root = create_root_from_ref(get_alloc(), ref); - new_root->set_parent(parent, ndx_in_parent); - m_root = std::move(new_root); - } - else { - m_root->detach(); - } -} - -template -typename BpTree::LeafType& BpTree::root_as_leaf() -{ - REALM_ASSERT_DEBUG(root_is_leaf()); - REALM_ASSERT_DEBUG(dynamic_cast(m_root.get()) != nullptr); - return static_cast(root()); -} - -template -const typename BpTree::LeafType& BpTree::root_as_leaf() const -{ - REALM_ASSERT_DEBUG(root_is_leaf()); - REALM_ASSERT_DEBUG(dynamic_cast(m_root.get()) != nullptr); - return static_cast(root()); -} - -template -size_t BpTree::size() const noexcept -{ - if (root_is_leaf()) { - return root_as_leaf().size(); - } - return root_as_node().get_bptree_size(); -} - -template -T BpTree::back() const noexcept -{ - // FIXME: slow - return get(size() - 1); -} - -namespace _impl { - -// NullableOrNothing encapsulates the behavior of nullable and -// non-nullable leaf types, so that non-nullable leaf types -// don't have to implement is_null/set_null but BpTree can still -// support the interface (and return false / assert when null -// is not supported). -template -struct NullableOrNothing { - static bool is_null(const Leaf& leaf, size_t ndx) - { - return leaf.is_null(ndx); - } - static void set_null(Leaf& leaf, size_t ndx) - { - leaf.set_null(ndx); - } -}; -template <> -struct NullableOrNothing { - static bool is_null(const ArrayInteger&, size_t) - { - return false; - } - static void set_null(ArrayInteger&, size_t) - { - REALM_ASSERT_RELEASE(false); - } -}; -} - -template -bool BpTree::is_null(size_t ndx) const noexcept -{ - if (root_is_leaf()) { - return _impl::NullableOrNothing::is_null(root_as_leaf(), ndx); - } - LeafType fallback(get_alloc()); - const LeafType* leaf; - LeafInfo leaf_info{&leaf, &fallback}; - size_t ndx_in_leaf; - get_leaf(ndx, ndx_in_leaf, leaf_info); - return _impl::NullableOrNothing::is_null(*leaf, ndx_in_leaf); -} - -template -T BpTree::get(size_t ndx) const noexcept -{ - REALM_ASSERT_DEBUG_EX(ndx < size(), ndx, size()); - if (root_is_leaf()) { - return root_as_leaf().get(ndx); - } - - // Use direct getter to avoid initializing leaf array: - std::pair p = root_as_node().get_bptree_leaf(ndx); - const char* leaf_header = p.first.get_addr(); - size_t ndx_in_leaf = p.second; - return LeafType::get(leaf_header, ndx_in_leaf); -} - -template -template -void BpTree::bptree_insert(size_t row_ndx, BpTreeNode::TreeInsert& state, size_t num_rows) -{ - ref_type new_sibling_ref; - for (size_t i = 0; i < num_rows; ++i) { - size_t row_ndx_2 = row_ndx == realm::npos ? realm::npos : row_ndx + i; - if (root_is_leaf()) { - REALM_ASSERT_DEBUG(row_ndx_2 == realm::npos || row_ndx_2 < REALM_MAX_BPNODE_SIZE); - new_sibling_ref = root_as_leaf().bptree_leaf_insert(row_ndx_2, state.m_value, state); - } - else { - if (row_ndx_2 == realm::npos) { - new_sibling_ref = root_as_node().bptree_append(state); // Throws - } - else { - new_sibling_ref = root_as_node().bptree_insert(row_ndx_2, state); // Throws - } - } - - if (REALM_UNLIKELY(new_sibling_ref)) { - bool is_append = row_ndx_2 == realm::npos; - introduce_new_root(new_sibling_ref, state, is_append); - } - } -} - -template -struct BpTree::LeafValueInserter { - using value_type = T; - T m_value; - LeafValueInserter(T value) - : m_value(std::move(value)) - { - } - - // TreeTraits concept: - static ref_type leaf_insert(MemRef leaf_mem, ArrayParent& parent, size_t ndx_in_parent, Allocator& alloc, - size_t ndx_in_leaf, BpTreeNode::TreeInsert& state) - { - LeafType leaf{alloc}; - leaf.init_from_mem(leaf_mem); - leaf.set_parent(&parent, ndx_in_parent); - // Should not move out of m_value, because the same inserter may be used to perform - // multiple insertions (for example, if num_rows > 1). - return leaf.bptree_leaf_insert(ndx_in_leaf, state.m_value, state); - } -}; - -template -struct BpTree::LeafNullInserter { - using value_type = null; - // TreeTraits concept: - static ref_type leaf_insert(MemRef leaf_mem, ArrayParent& parent, size_t ndx_in_parent, Allocator& alloc, - size_t ndx_in_leaf, BpTreeNode::TreeInsert& state) - { - LeafType leaf{alloc}; - leaf.init_from_mem(leaf_mem); - leaf.set_parent(&parent, ndx_in_parent); - return leaf.bptree_leaf_insert(ndx_in_leaf, null{}, state); - } -}; - -template -void BpTree::insert(size_t row_ndx, T value, size_t num_rows) -{ - REALM_ASSERT_DEBUG(row_ndx == npos || row_ndx < size()); - BpTreeNode::TreeInsert inserter; - inserter.m_value = std::move(value); - inserter.m_nullable = std::is_same>::value; // FIXME - bptree_insert(row_ndx, inserter, num_rows); // Throws -} - -template -struct BpTree::UpdateHandler : BpTreeNode::UpdateHandler { - LeafType m_leaf; - const T m_value; - UpdateHandler(BpTreeBase& tree, T value) noexcept - : m_leaf(tree.get_alloc()) - , m_value(std::move(value)) - { - } - void update(MemRef mem, ArrayParent* parent, size_t ndx_in_parent, size_t elem_ndx_in_leaf) override - { - m_leaf.init_from_mem(mem); - m_leaf.set_parent(parent, ndx_in_parent); - m_leaf.set(elem_ndx_in_leaf, m_value); // Throws - } -}; - -template -struct BpTree::SetNullHandler : BpTreeNode::UpdateHandler { - LeafType m_leaf; - SetNullHandler(BpTreeBase& tree) noexcept - : m_leaf(tree.get_alloc()) - { - } - void update(MemRef mem, ArrayParent* parent, size_t ndx_in_parent, size_t elem_ndx_in_leaf) override - { - m_leaf.init_from_mem(mem); - m_leaf.set_parent(parent, ndx_in_parent); - _impl::NullableOrNothing::set_null(m_leaf, elem_ndx_in_leaf); // Throws - } -}; - -template -void BpTree::set(size_t ndx, T value) -{ - if (root_is_leaf()) { - root_as_leaf().set(ndx, std::move(value)); - } - else { - UpdateHandler set_leaf_elem(*this, std::move(value)); - static_cast(m_root.get())->update_bptree_elem(ndx, set_leaf_elem); // Throws - } -} - -template -void BpTree::set_null(size_t ndx) -{ - if (root_is_leaf()) { - _impl::NullableOrNothing::set_null(root_as_leaf(), ndx); - } - else { - SetNullHandler set_leaf_elem(*this); - static_cast(m_root.get())->update_bptree_elem(ndx, set_leaf_elem); // Throws; - } -} - -template -struct BpTree::EraseHandler : BpTreeNode::EraseHandler { - BpTreeBase& m_tree; - LeafType m_leaf; - bool m_leaves_have_refs; // FIXME: Should be able to eliminate this. - EraseHandler(BpTreeBase& tree) noexcept - : m_tree(tree) - , m_leaf(tree.get_alloc()) - , m_leaves_have_refs(false) - { - } - bool erase_leaf_elem(MemRef leaf_mem, ArrayParent* parent, size_t leaf_ndx_in_parent, - size_t elem_ndx_in_leaf) override - { - m_leaf.init_from_mem(leaf_mem); - REALM_ASSERT_3(m_leaf.size(), >=, 1); - size_t last_ndx = m_leaf.size() - 1; - if (last_ndx == 0) { - m_leaves_have_refs = m_leaf.has_refs(); - return true; - } - m_leaf.set_parent(parent, leaf_ndx_in_parent); - size_t ndx = elem_ndx_in_leaf; - if (ndx == npos) - ndx = last_ndx; - m_leaf.erase(ndx); // Throws - return false; - } - void destroy_leaf(MemRef leaf_mem) noexcept override - { - // FIXME: Seems like this would cause file space leaks if - // m_leaves_have_refs is true, but consider carefully how - // m_leaves_have_refs get its value. - m_tree.get_alloc().free_(leaf_mem); - } - void replace_root_by_leaf(MemRef leaf_mem) override - { - std::unique_ptr leaf{new LeafType(m_tree.get_alloc())}; // Throws - leaf->init_from_mem(leaf_mem); - m_tree.replace_root(std::move(leaf)); // Throws - } - void replace_root_by_empty_leaf() override - { - std::unique_ptr leaf{new LeafType(m_tree.get_alloc())}; // Throws - leaf->create(m_leaves_have_refs ? Array::type_HasRefs : Array::type_Normal); // Throws - m_tree.replace_root(std::move(leaf)); // Throws - } -}; - -template -void BpTree::erase(size_t ndx, bool is_last) -{ - REALM_ASSERT_DEBUG_EX(ndx < size(), ndx, size()); - REALM_ASSERT_DEBUG(is_last == (ndx == size() - 1)); - if (root_is_leaf()) { - root_as_leaf().erase(ndx); - } - else { - size_t ndx_2 = is_last ? npos : ndx; - EraseHandler handler(*this); - BpTreeNode::erase_bptree_elem(&root_as_node(), ndx_2, handler); - } -} - -template -void BpTree::move_last_over(size_t row_ndx, size_t last_row_ndx) -{ - // Copy value from last row over - T value = get(last_row_ndx); - set(row_ndx, value); - erase(last_row_ndx, true); -} - -template -void BpTree::clear() -{ - if (root_is_leaf()) { - if (std::is_same::value && root().get_type() == Array::type_HasRefs) { - // FIXME: This is because some column types rely on integer columns - // to contain refs. - root().clear_and_destroy_children(); - } - else { - root_as_leaf().clear(); - } - } - else { - Allocator& alloc = get_alloc(); - root().destroy_deep(); - - std::unique_ptr new_root(new LeafType(alloc)); - new_root->create(); - replace_root(std::move(new_root)); - } -} - - -template -struct BpTree::AdjustHandler : BpTreeNode::UpdateHandler { - LeafType m_leaf; - const T m_diff; - AdjustHandler(BpTreeBase& tree, T diff) - : m_leaf(tree.get_alloc()) - , m_diff(diff) - { - } - - void update(MemRef mem, ArrayParent* parent, size_t ndx_in_parent, size_t) final - { - m_leaf.init_from_mem(mem); - m_leaf.set_parent(parent, ndx_in_parent); - m_leaf.adjust(0, m_leaf.size(), m_diff); - } -}; - -template -void BpTree::adjust(T diff) -{ - if (root_is_leaf()) { - root_as_leaf().adjust(0, m_root->size(), std::move(diff)); // Throws - } - else { - AdjustHandler adjust_leaf_elem(*this, std::move(diff)); - root_as_node().update_bptree_leaves(adjust_leaf_elem); // Throws - } -} - -template -void BpTree::adjust(size_t ndx, T diff) -{ - static_assert(std::is_arithmetic::value, "adjust is undefined for non-arithmetic trees"); - set(ndx, get(ndx) + diff); -} - -template -struct BpTree::AdjustGEHandler : BpTreeNode::UpdateHandler { - LeafType m_leaf; - const T m_limit, m_diff; - - AdjustGEHandler(BpTreeBase& tree, T limit, T diff) - : m_leaf(tree.get_alloc()) - , m_limit(limit) - , m_diff(diff) - { - } - - void update(MemRef mem, ArrayParent* parent, size_t ndx_in_parent, size_t) final - { - m_leaf.init_from_mem(mem); - m_leaf.set_parent(parent, ndx_in_parent); - m_leaf.adjust_ge(m_limit, m_diff); - } -}; - -template -void BpTree::adjust_ge(T limit, T diff) -{ - if (root_is_leaf()) { - root_as_leaf().adjust_ge(std::move(limit), std::move(diff)); // Throws - } - else { - AdjustGEHandler adjust_leaf_elem(*this, std::move(limit), std::move(diff)); - root_as_node().update_bptree_leaves(adjust_leaf_elem); // Throws - } -} - -template -struct BpTree::SliceHandler : public BpTreeBase::SliceHandler { -public: - SliceHandler(Allocator& alloc) - : m_leaf(alloc) - { - } - MemRef slice_leaf(MemRef leaf_mem, size_t offset, size_t size, Allocator& target_alloc) override - { - m_leaf.init_from_mem(leaf_mem); - return m_leaf.slice_and_clone_children(offset, size, target_alloc); // Throws - } - -private: - LeafType m_leaf; -}; - -template -ref_type BpTree::write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream& out) const -{ - ref_type ref; - if (root_is_leaf()) { - Allocator& alloc = Allocator::get_default(); - MemRef mem = root_as_leaf().slice_and_clone_children(slice_offset, slice_size, alloc); // Throws - Array slice(alloc); - _impl::DeepArrayDestroyGuard dg(&slice); - slice.init_from_mem(mem); - bool deep = true; - bool only_when_modified = false; - ref = slice.write(out, deep, only_when_modified); // Throws - } - else { - SliceHandler handler(get_alloc()); - ref = write_subtree(root_as_node(), slice_offset, slice_size, table_size, handler, out); // Throws - } - return ref; -} - -template -MemRef BpTree::create_leaf(Array::Type leaf_type, size_t size, T value, Allocator& alloc) -{ - bool context_flag = false; - MemRef mem = LeafType::create_array(leaf_type, context_flag, size, std::move(value), alloc); - return mem; -} - -template -void BpTree::get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf_info) const noexcept -{ - if (root_is_leaf()) { - ndx_in_leaf = ndx; - *inout_leaf_info.out_leaf = &root_as_leaf(); - return; - } - std::pair p = root_as_node().get_bptree_leaf(ndx); - inout_leaf_info.fallback->init_from_mem(p.first); - ndx_in_leaf = p.second; - *inout_leaf_info.out_leaf = inout_leaf_info.fallback; -} - -template -size_t BpTree::find_first(T value, size_t begin, size_t end) const -{ - if (root_is_leaf()) { - return root_as_leaf().find_first(value, begin, end); - } - - // FIXME: It would be better to always require that 'end' is - // specified explicitly, since Table has the size readily - // available, and Array::get_bptree_size() is deprecated. - if (end == npos) - end = size(); - - LeafType leaf_cache(get_alloc()); - size_t ndx_in_tree = begin; - while (ndx_in_tree < end) { - const LeafType* leaf; - LeafInfo leaf_info{&leaf, &leaf_cache}; - size_t ndx_in_leaf; - get_leaf(ndx_in_tree, ndx_in_leaf, leaf_info); - size_t leaf_offset = ndx_in_tree - ndx_in_leaf; - size_t end_in_leaf = std::min(leaf->size(), end - leaf_offset); - size_t ndx = leaf->find_first(value, ndx_in_leaf, end_in_leaf); // Throws (maybe) - if (ndx != not_found) - return leaf_offset + ndx; - ndx_in_tree = leaf_offset + end_in_leaf; - } - - return not_found; -} - -template -void BpTree::find_all(IntegerColumn& result, T value, size_t begin, size_t end) const -{ - if (root_is_leaf()) { - root_as_leaf().find_all(&result, value, 0, begin, end); // Throws - return; - } - - // FIXME: It would be better to always require that 'end' is - // specified explicitely, since Table has the size readily - // available, and Array::get_bptree_size() is deprecated. - if (end == npos) - end = size(); - - LeafType leaf_cache(get_alloc()); - size_t ndx_in_tree = begin; - while (ndx_in_tree < end) { - const LeafType* leaf; - LeafInfo leaf_info{&leaf, &leaf_cache}; - size_t ndx_in_leaf; - get_leaf(ndx_in_tree, ndx_in_leaf, leaf_info); - size_t leaf_offset = ndx_in_tree - ndx_in_leaf; - size_t end_in_leaf = std::min(leaf->size(), end - leaf_offset); - leaf->find_all(&result, value, leaf_offset, ndx_in_leaf, end_in_leaf); // Throws - ndx_in_tree = leaf_offset + end_in_leaf; - } -} - -#if defined(REALM_DEBUG) -template -size_t BpTree::verify_leaf(MemRef mem, Allocator& alloc) -{ - LeafType leaf(alloc); - leaf.init_from_mem(mem); - leaf.verify(); - return leaf.size(); -} - -template -void BpTree::verify() const -{ - if (root_is_leaf()) { - root_as_leaf().verify(); - } - else { - root().verify_bptree(&verify_leaf); - } -} -#endif // REALM_DEBUG - -template -void BpTree::leaf_to_dot(MemRef leaf_mem, ArrayParent* parent, size_t ndx_in_parent, std::ostream& out, - Allocator& alloc) -{ - LeafType leaf(alloc); - leaf.init_from_mem(leaf_mem); - leaf.set_parent(parent, ndx_in_parent); - leaf.to_dot(out); -} - -} // namespace realm - -#endif // REALM_BPTREE_HPP diff --git a/Example/Pods/Realm/include/core/realm/column.hpp b/Example/Pods/Realm/include/core/realm/column.hpp deleted file mode 100644 index 5f3cfd8..0000000 --- a/Example/Pods/Realm/include/core/realm/column.hpp +++ /dev/null @@ -1,1853 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_HPP -#define REALM_COLUMN_HPP - -#include // unint8_t etc -#include // size_t -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - - -// Pre-definitions -struct CascadeState; -class StringIndex; - -template -struct ImplicitNull; - -template -struct ImplicitNull> { - static constexpr bool value = true; -}; - -template <> -struct ImplicitNull { - static constexpr bool value = false; -}; - -template <> -struct ImplicitNull { - static constexpr bool value = true; -}; - -template <> -struct ImplicitNull { - static constexpr bool value = true; -}; - -// FIXME: Add specialization for ImplicitNull for float, double, StringData, BinaryData. - -template -R aggregate(const ColType& column, T target, size_t start, size_t end, size_t limit, size_t* return_ndx); - - -// Iterator with random access for Columns -template -class ColumnRandIterator : public std::iterator { -public: - ColumnRandIterator(const Column* src_col, size_t ndx = 0); - bool operator==(const ColumnRandIterator& rhs) const; - bool operator!=(const ColumnRandIterator& rhs) const; - bool operator<(const ColumnRandIterator& rhs) const; - bool operator>(const ColumnRandIterator& rhs) const; - bool operator<=(const ColumnRandIterator& rhs) const; - bool operator>=(const ColumnRandIterator& rhs) const; - ColumnRandIterator& operator+=(ptrdiff_t movement); - ColumnRandIterator& operator-=(ptrdiff_t movement); - ColumnRandIterator& operator++(); - ColumnRandIterator& operator--(); - ColumnRandIterator operator++(int); - ColumnRandIterator operator--(int); - ColumnRandIterator operator+(ptrdiff_t movement); - ColumnRandIterator operator-(ptrdiff_t movement); - ptrdiff_t operator-(const ColumnRandIterator& rawIterator); - const ColumnDataType operator*() const; - const ColumnDataType operator->() const; - const ColumnDataType operator[](ptrdiff_t offset) const; - size_t get_col_ndx() const; -protected: - size_t m_col_ndx; - const Column* m_col; -}; - -/// Base class for all column types. -class ColumnBase { -public: - /// Get the number of entries in this column. This operation is relatively - /// slow. - virtual size_t size() const noexcept = 0; - - /// \throw LogicError Thrown if this column is not string valued. - virtual void set_string(size_t row_ndx, StringData value); - - /// Whether or not this column is nullable. - virtual bool is_nullable() const noexcept; - - /// Whether or not the value at \a row_ndx is NULL. If the column is not - /// nullable, always returns false. - virtual bool is_null(size_t row_ndx) const noexcept; - - /// Sets the value at \a row_ndx to be NULL. - /// \throw LogicError Thrown if this column is not nullable. - virtual void set_null(size_t row_ndx); - - /// Inserts the specified number of elements into this column - /// starting at the specified row index. The new elements will have the - /// default value for the column type. - /// - /// \param row_ndx The row to start insertion at. If the row_ndx is less - /// than prior_num_rows then previous rows from row_ndx onwards will be - /// moved ahead by num_rows_to_insert. - /// - /// \param num_rows_to_insert The number of rows to insert. There is no - /// restriction on this value. - /// - /// \param prior_num_rows The number of elements in this column prior to the - /// modification. - /// - /// \param nullable Specifies whether or not this column is nullable. This - /// function may assert if nullable does not agree with \a is_nullable() - virtual void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) = 0; - - /// Removes the specified number of consecutive elements from - /// this column, starting at the specified row index. - /// - /// \param row_ndx The row to start removal at (inclusive). This must be - /// less than prior_num_rows. - /// - /// \param num_rows_to_erase The number of rows to erase. - /// The row_ndx + num_rows_to_erase must be less than prior_num_rows. - /// - /// \param prior_num_rows The number of elements in this column prior to the - /// modification. - /// - /// \param broken_reciprocal_backlinks If true, link columns must assume - /// that reciprocal backlinks have already been removed. Non-link columns - /// should ignore this argument. - virtual void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, - bool broken_reciprocal_backlinks) = 0; - - /// Removes the element at the specified row index by - /// moving the element at the last row index over it. This reduces the - /// number of elements by one. - /// - /// \param row_ndx The row to erase. Must be less than prior_num_rows. - /// - /// \param prior_num_rows The number of elements in this column prior to the - /// modification. - /// - /// \param broken_reciprocal_backlinks If true, link columns must assume - /// that reciprocal backlinks have already been removed. Non-link columns - /// should ignore this argument. - virtual void move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool broken_reciprocal_backlinks) = 0; - - /// Remove all elements from this column. - /// - /// \param num_rows The total number of rows in this column. - /// - /// \param broken_reciprocal_backlinks If true, link columns must assume - /// that reciprocal backlinks have already been removed. Non-link columns - /// should ignore this argument. - virtual void clear(size_t num_rows, bool broken_reciprocal_backlinks) = 0; - - /// \brief Swap the elements at the specified indices. - /// - /// Behaviour is undefined if: - /// - \a row_ndx_1 or \a row_ndx_2 point to an invalid element (out-of - /// bounds) - /// - \a row_ndx_1 and \a row_ndx_2 point to the same value - virtual void swap_rows(size_t row_ndx_1, size_t row_ndx_2) = 0; - - virtual void destroy() noexcept = 0; - void move_assign(ColumnBase& col) noexcept; - - virtual ~ColumnBase() noexcept - { - } - - // Getter function for index. For integer index, the caller must supply a - // buffer that we can store the extracted value in (it may be bitpacked, so - // we cannot return a pointer in to the Array as we do with String index). - virtual StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept = 0; - - // Search index - virtual bool supports_search_index() const noexcept; - virtual bool has_search_index() const noexcept; - virtual StringIndex* create_search_index(); - virtual void destroy_search_index() noexcept; - virtual const StringIndex* get_search_index() const noexcept; - virtual StringIndex* get_search_index() noexcept; - virtual void set_search_index_ref(ref_type, ArrayParent*, size_t ndx_in_parent, bool allow_duplicate_values); - virtual void set_search_index_allow_duplicate_values(bool) noexcept; - - virtual Allocator& get_alloc() const noexcept = 0; - - /// Returns the 'ref' of the root array. - virtual ref_type get_ref() const noexcept = 0; - virtual MemRef get_mem() const noexcept = 0; - - virtual void replace_root_array(std::unique_ptr leaf) = 0; - virtual MemRef clone_deep(Allocator& alloc) const = 0; - virtual void detach(void) = 0; - virtual bool is_attached(void) const noexcept = 0; - - static size_t get_size_from_type_and_ref(ColumnType, ref_type, Allocator&, bool) noexcept; - - // These assume that the right column compile-time type has been - // figured out. - static size_t get_size_from_ref(ref_type root_ref, Allocator&); - static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator&); - - /// Write a slice of this column to the specified output stream. - virtual ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const = 0; - - /// Get this column's logical index within the containing table, or npos - /// for free-standing or non-top-level columns. - size_t get_column_index() const noexcept - { - return m_column_ndx; - } - - virtual void set_parent(ArrayParent*, size_t ndx_in_parent) noexcept = 0; - virtual size_t get_ndx_in_parent() const noexcept = 0; - virtual void set_ndx_in_parent(size_t ndx_in_parent) noexcept = 0; - - /// Called to update refs and memory pointers of this column accessor and - /// all its nested accessors, but only in cases where the logical contents - /// in strictly unchanged. Group::commit(), and - /// SharedGroup::commit_and_continue_as_read()() are examples of such - /// cases. In both those cases, the purpose is to keep user visible - /// accessors in a valid state across a commit. - virtual void update_from_parent(size_t old_baseline) noexcept = 0; - - //@{ - - /// cascade_break_backlinks_to() is called iteratively for each column by - /// Table::cascade_break_backlinks_to() with the same arguments as are - /// passed to Table::cascade_break_backlinks_to(). Link columns must - /// override it. The same is true for cascade_break_backlinks_to_all_rows(), - /// except that it is called from - /// Table::cascade_break_backlinks_to_all_rows(), and that it expects - /// Table::cascade_break_backlinks_to_all_rows() to pass the number of rows - /// in the table as \a num_rows. - - virtual void cascade_break_backlinks_to(size_t row_ndx, CascadeState&); - virtual void cascade_break_backlinks_to_all_rows(size_t num_rows, CascadeState&); - - //@} - - void discard_child_accessors() noexcept; - - /// For columns that are able to contain subtables, this function returns - /// the pointer to the subtable accessor at the specified row index if it - /// exists, otherwise it returns null. For other column types, this function - /// returns null. - virtual Table* get_subtable_accessor(size_t row_ndx) const noexcept; - - /// Detach and remove the subtable accessor at the specified row if it - /// exists. For column types that are unable to contain subtable, this - /// function does nothing. - virtual void discard_subtable_accessor(size_t row_ndx) noexcept; - - virtual void adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept; - virtual void adj_acc_erase_row(size_t row_ndx) noexcept; - /// See Table::adj_acc_move_over() - virtual void adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; - virtual void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - virtual void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; - virtual void adj_acc_clear_root_table() noexcept; - - enum { - mark_Recursive = 0x01, - mark_LinkTargets = 0x02, - mark_LinkOrigins = 0x04, - }; - - virtual void mark(int type) noexcept; - - virtual void bump_link_origin_table_version() noexcept; - - virtual int compare_values(size_t row1, size_t row2) const noexcept = 0; - - /// Refresh the dirty part of the accessor subtree rooted at this column - /// accessor. - /// - /// The following conditions are necessary and sufficient for the proper - /// operation of this function: - /// - /// - The parent table accessor (excluding its column accessors) is in a - /// valid state (already refreshed). - /// - /// - Every subtable accessor in the subtree is marked dirty if it needs to - /// be refreshed, or if it has a descendant accessor that needs to be - /// refreshed. - /// - /// - This column accessor, as well as all its descendant accessors, are in - /// structural correspondence with the underlying node hierarchy whose - /// root ref is stored in the parent (`Table::m_columns`) (see - /// AccessorConsistencyLevels). - /// - /// - The 'index in parent' property of the cached root array - /// (`root->m_ndx_in_parent`) is valid. - virtual void refresh_accessor_tree(size_t new_col_ndx, const Spec&); - - virtual void verify() const = 0; - virtual void verify(const Table&, size_t col_ndx) const; - virtual void to_dot(std::ostream&, StringData title = StringData()) const = 0; - virtual void do_dump_node_structure(std::ostream&, int level) const = 0; - -#ifdef REALM_DEBUG - void dump_node_structure() const; // To std::cerr (for GDB) - void bptree_to_dot(const Array* root, std::ostream& out) const; -#endif - -protected: - using SliceHandler = BpTreeBase::SliceHandler; - - ColumnBase(size_t column_ndx = npos) - : m_column_ndx(column_ndx) - { - } - ColumnBase(ColumnBase&&) = default; - - // Must not assume more than minimal consistency (see - // AccessorConsistencyLevels). - virtual void do_discard_child_accessors() noexcept - { - } - - //@{ - /// \tparam L Any type with an appropriate `value_type`, %size(), - /// and %get() members. - template - size_t lower_bound(const L& list, T value) const noexcept; - - template - size_t upper_bound(const L& list, T value) const noexcept; - //@} - - // Node functions - - class CreateHandler { - public: - virtual ref_type create_leaf(size_t size) = 0; - ~CreateHandler() noexcept - { - } - }; - - static ref_type create(Allocator&, size_t size, CreateHandler&); - - class LeafToDot; - virtual void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const = 0; - - template - static int compare_values(const Column* column, size_t row1, size_t row2) noexcept; - -private: - size_t m_column_ndx = npos; - - static ref_type build(size_t* rest_size_ptr, size_t fixed_height, Allocator&, CreateHandler&); -}; - - -// FIXME: Temporary class until all column types have been migrated to use BpTree interface -class ColumnBaseSimple : public ColumnBase { -public: - //@{ - /// Returns the array node at the root of this column, but note - /// that there is no guarantee that this node is an inner B+-tree - /// node or a leaf. This is the case for a MixedColumn in - /// particular. - Array* get_root_array() noexcept - { - return m_array.get(); - } - const Array* get_root_array() const noexcept - { - return m_array.get(); - } - //@} - - Allocator& get_alloc() const noexcept final - { - return m_array->get_alloc(); - } - void destroy() noexcept override - { - if (m_array) - m_array->destroy_deep(); - } - ref_type get_ref() const noexcept final - { - return m_array->get_ref(); - } - MemRef get_mem() const noexcept final - { - return m_array->get_mem(); - } - void detach() noexcept final - { - m_array->detach(); - } - bool is_attached() const noexcept final - { - return m_array->is_attached(); - } - void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept final - { - m_array->set_parent(parent, ndx_in_parent); - } - size_t get_ndx_in_parent() const noexcept final - { - return m_array->get_ndx_in_parent(); - } - void set_ndx_in_parent(size_t ndx_in_parent) noexcept override - { - m_array->set_ndx_in_parent(ndx_in_parent); - } - void update_from_parent(size_t old_baseline) noexcept override - { - m_array->update_from_parent(old_baseline); - } - MemRef clone_deep(Allocator& alloc) const override - { - return m_array->clone_deep(alloc); - } - -protected: - ColumnBaseSimple(size_t column_ndx) - : ColumnBase(column_ndx) - { - } - ColumnBaseSimple(Array* root) - : m_array(root) - { - } - std::unique_ptr m_array; - - void replace_root_array(std::unique_ptr new_root) final; - bool root_is_leaf() const noexcept - { - return !m_array->is_inner_bptree_node(); - } - - /// Introduce a new root node which increments the height of the - /// tree by one. - void introduce_new_root(ref_type new_sibling_ref, TreeInsertBase& state, bool is_append); - - static ref_type write(const Array* root, size_t slice_offset, size_t slice_size, size_t table_size, SliceHandler&, - _impl::OutputStream&); - -#if defined(REALM_DEBUG) - void tree_to_dot(std::ostream&) const; -#endif -}; - -class ColumnBaseWithIndex : public ColumnBase { -public: - ~ColumnBaseWithIndex() noexcept override - { - } - void set_ndx_in_parent(size_t ndx) noexcept override; - void update_from_parent(size_t old_baseline) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - void move_assign(ColumnBaseWithIndex& col) noexcept; - void destroy() noexcept override; - - virtual bool supports_search_index() const noexcept override - { - return true; - } - bool has_search_index() const noexcept final - { - return bool(m_search_index); - } - StringIndex* get_search_index() noexcept final - { - return m_search_index.get(); - } - const StringIndex* get_search_index() const noexcept final - { - return m_search_index.get(); - } - void destroy_search_index() noexcept override; - void set_search_index_ref(ref_type ref, ArrayParent* parent, size_t ndx_in_parent, - bool allow_duplicate_valaues) final; - StringIndex* create_search_index() override = 0; - -protected: - using ColumnBase::ColumnBase; - ColumnBaseWithIndex(ColumnBaseWithIndex&&) = default; - std::unique_ptr m_search_index; -}; - - -/// A column (Column) is a single B+-tree, and the root of -/// the column is the root of the B+-tree. All leaf nodes are arrays. -template -class Column : public ColumnBaseWithIndex { -public: - using value_type = T; - using LeafInfo = typename BpTree::LeafInfo; - using LeafType = typename BpTree::LeafType; - - static constexpr bool nullable = ImplicitNull::value; - - struct unattached_root_tag { - }; - - explicit Column() noexcept - : ColumnBaseWithIndex(npos) - , m_tree(Allocator::get_default()) - { - } - REALM_DEPRECATED("Initialize with ref instead") explicit Column(std::unique_ptr root) noexcept; - Column(Allocator&, ref_type, size_t column_ndx = npos); - Column(unattached_root_tag, Allocator&); - Column(Column&&) noexcept = default; - ~Column() noexcept override; - - void init_from_parent(); - void init_from_ref(Allocator&, ref_type); - void init_from_mem(Allocator&, MemRef); - // Accessor concept: - void destroy() noexcept override; - Allocator& get_alloc() const noexcept final; - ref_type get_ref() const noexcept final; - MemRef get_mem() const noexcept final; - void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept override; - size_t get_ndx_in_parent() const noexcept final; - void set_ndx_in_parent(size_t ndx) noexcept final; - void update_from_parent(size_t old_baseline) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - void detach() noexcept final; - bool is_attached() const noexcept final; - MemRef clone_deep(Allocator&) const override; - - void move_assign(Column&); - - static size_t get_size_from_ref(ref_type root_ref, Allocator& alloc) - { - return ColumnBase::get_size_from_ref(root_ref, alloc); - } - - size_t size() const noexcept override; - bool is_empty() const noexcept - { - return size() == 0; - } - bool is_nullable() const noexcept override; - - /// Provides access to the leaf that contains the element at the - /// specified index. Upon return \a ndx_in_leaf will be set to the - /// corresponding index relative to the beginning of the leaf. - /// - /// LeafInfo is a struct defined by the underlying BpTree - /// data structure, that provides a way for the caller to do - /// leaf caching without instantiating too many objects along - /// the way. - /// - /// This function cannot be used for modifying operations as it - /// does not ensure the presence of an unbroken chain of parent - /// accessors. For this reason, the identified leaf should always - /// be accessed through the returned const-qualified reference, - /// and never directly through the specfied fallback accessor. - void get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf) const noexcept; - - // Getting and setting values - T get(size_t ndx) const noexcept; - bool is_null(size_t ndx) const noexcept override; - T back() const noexcept; - void set(size_t, T value); - void set_null(size_t) override; - void add(T value = T{}); - void insert(size_t ndx, T value = T{}, size_t num_rows = 1); - void erase(size_t row_ndx); - void erase(size_t row_ndx, bool is_last); - void move_last_over(size_t row_ndx, size_t last_row_ndx); - void clear(); - - // Index support - StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept override; - - // FIXME: Remove these - uint64_t get_uint(size_t ndx) const noexcept; - ref_type get_as_ref(size_t ndx) const noexcept; - void set_uint(size_t ndx, uint64_t value); - void set_as_ref(size_t ndx, ref_type value); - - template - void adjust(size_t ndx, U diff); - - template - void adjust(U diff); - - template - void adjust_ge(T limit, U diff); - - size_t count(T target) const; - - typename ColumnTypeTraits::sum_type sum(size_t start = 0, size_t end = npos, size_t limit = npos, - size_t* return_ndx = nullptr) const; - - typename ColumnTypeTraits::minmax_type maximum(size_t start = 0, size_t end = npos, size_t limit = npos, - size_t* return_ndx = nullptr) const; - - typename ColumnTypeTraits::minmax_type minimum(size_t start = 0, size_t end = npos, size_t limit = npos, - size_t* return_ndx = nullptr) const; - - double average(size_t start = 0, size_t end = npos, size_t limit = npos, size_t* return_ndx = nullptr) const; - - size_t find_first(T value, size_t begin = 0, size_t end = npos) const; - void find_all(Column& out_indices, T value, size_t begin = 0, size_t end = npos) const; - - void populate_search_index(); - StringIndex* create_search_index() override; - inline bool supports_search_index() const noexcept override - { - if (realm::is_any::value) - return false; - else - return true; - } - - - //@{ - /// Find the lower/upper bound for the specified value assuming - /// that the elements are already sorted in ascending order - /// according to ordinary integer comparison. - size_t lower_bound(T value) const noexcept; - size_t upper_bound(T value) const noexcept; - //@} - - using const_iterator = ColumnRandIterator; - - const_iterator cbegin() const - { - return const_iterator(this, 0); // `this` is const in a const method - } - const_iterator cend() const - { - return const_iterator(this, size()); - } - - size_t find_gte(T target, size_t start) const; - - bool compare(const Column&) const noexcept; - int compare_values(size_t row1, size_t row2) const noexcept override; - - static ref_type create(Allocator&, Array::Type leaf_type = Array::type_Normal, size_t size = 0, T value = T{}); - - // Overriding method in ColumnBase - ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - - /// \brief Swap the elements at the specified indices. - /// - /// If this \c Column has a search index defined, it will be updated to - /// reflect the changes induced by the swap. - /// - /// Behaviour is undefined if: - /// - \a row_ndx_1 or \a row_ndx_2 point to an invalid element (out-of - /// bounds) - /// - \a row_ndx_1 and \a row_ndx_2 point to the same value - void swap_rows(size_t, size_t) override; - void clear(size_t, bool) override; - - /// \param row_ndx Must be `realm::npos` if appending. - /// \param value The value to store at the specified row. - /// \param num_rows The number of rows to insert. - void insert_without_updating_index(size_t row_ndx, T value, size_t num_rows); - - void verify() const override; - void to_dot(std::ostream&, StringData title) const override; - void do_dump_node_structure(std::ostream&, int) const override; -#ifdef REALM_DEBUG - using ColumnBase::verify; - void tree_to_dot(std::ostream&) const; - MemStats stats() const; -#endif - - //@{ - /// Returns the array node at the root of this column, but note - /// that there is no guarantee that this node is an inner B+-tree - /// node or a leaf. This is the case for a MixedColumn in - /// particular. - Array* get_root_array() noexcept - { - return &m_tree.root(); - } - const Array* get_root_array() const noexcept - { - return &m_tree.root(); - } - //@} - -protected: - bool root_is_leaf() const noexcept - { - return m_tree.root_is_leaf(); - } - void replace_root_array(std::unique_ptr leaf) final - { - m_tree.replace_root(std::move(leaf)); - } - - void set_without_updating_index(size_t row_ndx, T value); - void erase_without_updating_index(size_t row_ndx, bool is_last); - void move_last_over_without_updating_index(size_t row_ndx, size_t last_row_ndx); - void swap_rows_without_updating_index(size_t row_ndx_1, size_t row_ndx_2); - - /// If any element points to an array node, this function recursively - /// destroys that array node. Note that the same is **not** true for - /// IntegerColumn::do_erase() and IntegerColumn::do_move_last_over(). - /// - /// FIXME: Be careful, clear_without_updating_index() currently forgets - /// if the leaf type is Array::type_HasRefs. - void clear_without_updating_index(); - - void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; -#ifdef REALM_DEBUG - static void dump_node_structure(const Array& root, std::ostream&, int level); -#endif - std::pair get_to_dot_parent(size_t ndx_in_parent) const; - -private: - class EraseLeafElem; - class CreateHandler; - class SliceHandler; - - friend class Array; - friend class ColumnBase; - friend class StringIndex; - - BpTree m_tree; - - void do_erase(size_t row_ndx, size_t num_rows_to_erase, bool is_last); -}; - -// Implementation: - - -template <> -inline size_t IntNullColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc) -{ - // FIXME: Speed improvement possible by not creating instance, but tricky! This slow method is OK so far - // because it's only invoked by Table::get_size_from_ref() which is only used for subtables which we - // currently 2016) do not expose publicly. - IntNullColumn inc(alloc, root_ref); - return inc.size(); -} - - -inline bool ColumnBase::supports_search_index() const noexcept -{ - REALM_ASSERT(!has_search_index()); - return false; -} - -inline bool ColumnBase::has_search_index() const noexcept -{ - return get_search_index() != nullptr; -} - -inline StringIndex* ColumnBase::create_search_index() -{ - return nullptr; -} - -inline void ColumnBase::destroy_search_index() noexcept -{ -} - -inline const StringIndex* ColumnBase::get_search_index() const noexcept -{ - return nullptr; -} - -inline StringIndex* ColumnBase::get_search_index() noexcept -{ - return nullptr; -} - -inline void ColumnBase::set_search_index_ref(ref_type, ArrayParent*, size_t, bool) -{ -} - -inline void ColumnBase::set_search_index_allow_duplicate_values(bool) noexcept -{ -} - -inline void ColumnBase::discard_child_accessors() noexcept -{ - do_discard_child_accessors(); -} - -inline Table* ColumnBase::get_subtable_accessor(size_t) const noexcept -{ - return 0; -} - -inline void ColumnBase::discard_subtable_accessor(size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_insert_rows(size_t, size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_erase_row(size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_move_over(size_t, size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_swap_rows(size_t, size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_merge_rows(size_t, size_t) noexcept -{ - // Noop -} - -inline void ColumnBase::adj_acc_clear_root_table() noexcept -{ - // Noop -} - -inline void ColumnBase::mark(int) noexcept -{ - // Noop -} - -inline void ColumnBase::bump_link_origin_table_version() noexcept -{ - // Noop -} - -template -int ColumnBase::compare_values(const Column* column, size_t row1, size_t row2) noexcept -{ - // we negate nullability such that the two ternary statements in this method can look identical to reduce - // risk of bugs - bool v1 = !column->is_null(row1); - bool v2 = !column->is_null(row2); - - if (!v1 || !v2) - return v1 == v2 ? 0 : v1 < v2 ? 1 : -1; - - auto a = column->get(row1); - auto b = column->get(row2); - return a == b ? 0 : a < b ? 1 : -1; -} - -template -void Column::set_without_updating_index(size_t ndx, T value) -{ - m_tree.set(ndx, std::move(value)); -} - -template -void Column::set(size_t ndx, T value) -{ - REALM_ASSERT_DEBUG(ndx < size()); - if (has_search_index()) { - m_search_index->set(ndx, value); - } - set_without_updating_index(ndx, std::move(value)); -} - -template -void Column::set_null(size_t ndx) -{ - REALM_ASSERT_DEBUG(ndx < size()); - if (!is_nullable()) { - throw LogicError{LogicError::column_not_nullable}; - } - if (has_search_index()) { - m_search_index->set(ndx, null{}); - } - m_tree.set_null(ndx); -} - -// When a value of a signed type is converted to an unsigned type, the C++ standard guarantees that negative values -// are converted from the native representation to 2's complement, but the opposite conversion is left as undefined. -// realm::util::from_twos_compl() is used here to perform the correct opposite unsigned-to-signed conversion, -// which reduces to a no-op when 2's complement is the native representation of negative values. -template -void Column::set_uint(size_t ndx, uint64_t value) -{ - set(ndx, util::from_twos_compl(value)); -} - -template -void Column::set_as_ref(size_t ndx, ref_type ref) -{ - set(ndx, from_ref(ref)); -} - -template -template -void Column::adjust(size_t ndx, U diff) -{ - REALM_ASSERT_3(ndx, <, size()); - m_tree.adjust(ndx, diff); -} - -template -template -void Column::adjust(U diff) -{ - m_tree.adjust(diff); -} - -template -template -void Column::adjust_ge(T limit, U diff) -{ - m_tree.adjust_ge(limit, diff); -} - -template -size_t Column::count(T target) const -{ - if (has_search_index()) { - return m_search_index->count(target); - } - return to_size_t(aggregate(*this, target, 0, size(), npos, nullptr)); -} - -template -typename ColumnTypeTraits::sum_type Column::sum(size_t start, size_t end, size_t limit, - size_t* return_ndx) const -{ - using sum_type = typename ColumnTypeTraits::sum_type; - if (nullable) - return aggregate(*this, 0, start, end, limit, return_ndx); - else - return aggregate(*this, 0, start, end, limit, return_ndx); -} - -template -double Column::average(size_t start, size_t end, size_t limit, size_t* return_ndx) const -{ - if (end == size_t(-1)) - end = size(); - - auto s = sum(start, end, limit); - size_t cnt = to_size_t(aggregate(*this, 0, start, end, limit, nullptr)); - if (return_ndx) - *return_ndx = cnt; - double avg = double(s) / (cnt == 0 ? 1 : cnt); - return avg; -} - -template -typename ColumnTypeTraits::minmax_type Column::minimum(size_t start, size_t end, size_t limit, - size_t* return_ndx) const -{ - using R = typename ColumnTypeTraits::minmax_type; - return aggregate(*this, 0, start, end, limit, return_ndx); -} - -template -typename ColumnTypeTraits::minmax_type Column::maximum(size_t start, size_t end, size_t limit, - size_t* return_ndx) const -{ - using R = typename ColumnTypeTraits::minmax_type; - return aggregate(*this, 0, start, end, limit, return_ndx); -} - -template -void Column::get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf_info) const noexcept -{ - m_tree.get_leaf(ndx, ndx_in_leaf, inout_leaf_info); -} - -template -StringData Column::get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept -{ - T x = get(ndx); - return to_str(x, buffer); -} - -template -void Column::populate_search_index() -{ - REALM_ASSERT(has_search_index()); - // Populate the index - size_t num_rows = size(); - for (size_t row_ndx = 0; row_ndx != num_rows; ++row_ndx) { - bool is_append = true; - if (is_null(row_ndx)) { - m_search_index->insert(row_ndx, null{}, 1, is_append); // Throws - } - else { - T value = get(row_ndx); - m_search_index->insert(row_ndx, value, 1, is_append); // Throws - } - } -} - -template -StringIndex* Column::create_search_index() -{ - if (realm::is_any::value) - return nullptr; - - REALM_ASSERT(!has_search_index()); - REALM_ASSERT(supports_search_index()); - m_search_index.reset(new StringIndex(this, get_alloc())); // Throws - populate_search_index(); - return m_search_index.get(); -} - -template -size_t Column::find_first(T value, size_t begin, size_t end) const -{ - REALM_ASSERT_3(begin, <=, size()); - REALM_ASSERT(end == npos || (begin <= end && end <= size())); - - if (m_search_index && begin == 0 && end == npos) - return m_search_index->find_first(value); - return m_tree.find_first(value, begin, end); -} - -template -void Column::find_all(IntegerColumn& result, T value, size_t begin, size_t end) const -{ - REALM_ASSERT_3(begin, <=, size()); - REALM_ASSERT(end == npos || (begin <= end && end <= size())); - - if (m_search_index && begin == 0 && end == npos) - return m_search_index->find_all(result, value); - return m_tree.find_all(result, value, begin, end); -} - -inline size_t ColumnBase::get_size_from_ref(ref_type root_ref, Allocator& alloc) -{ - const char* root_header = alloc.translate(root_ref); - bool root_is_leaf = !Array::get_is_inner_bptree_node_from_header(root_header); - if (root_is_leaf) - return Array::get_size_from_header(root_header); - return BpTreeNode::get_bptree_size_from_header(root_header); -} - -template -size_t ColumnBase::lower_bound(const L& list, T value) const noexcept -{ - size_t i = 0; - size_t list_size = list.size(); - while (0 < list_size) { - size_t half = list_size / 2; - size_t mid = i + half; - typename L::value_type probe = list.get(mid); - if (probe < value) { - i = mid + 1; - list_size -= half + 1; - } - else { - list_size = half; - } - } - return i; -} - -template -size_t ColumnBase::upper_bound(const L& list, T value) const noexcept -{ - size_t i = 0; - size_t list_size = list.size(); - while (0 < list_size) { - size_t half = list_size / 2; - size_t mid = i + half; - typename L::value_type probe = list.get(mid); - if (!(value < probe)) { - i = mid + 1; - list_size -= half + 1; - } - else { - list_size = half; - } - } - return i; -} - - -inline ref_type ColumnBase::create(Allocator& alloc, size_t column_size, CreateHandler& handler) -{ - size_t rest_size = column_size; - size_t fixed_height = 0; // Not fixed - return build(&rest_size, fixed_height, alloc, handler); -} - -template -Column::Column(Allocator& alloc, ref_type ref, size_t column_ndx) - : ColumnBaseWithIndex(column_ndx) - , m_tree(BpTreeBase::unattached_tag{}) -{ - // fixme, must m_search_index be copied here? - m_tree.init_from_ref(alloc, ref); -} - -template -Column::Column(unattached_root_tag, Allocator& alloc) - : ColumnBaseWithIndex(npos) - , m_tree(alloc) -{ -} - -template -Column::Column(std::unique_ptr root) noexcept - : m_tree(std::move(root)) -{ -} - -template -Column::~Column() noexcept -{ -} - -template -void Column::init_from_parent() -{ - m_tree.init_from_parent(); -} - -template -void Column::init_from_ref(Allocator& alloc, ref_type ref) -{ - m_tree.init_from_ref(alloc, ref); -} - -template -void Column::init_from_mem(Allocator& alloc, MemRef mem) -{ - m_tree.init_from_mem(alloc, mem); -} - -template -void Column::destroy() noexcept -{ - ColumnBaseWithIndex::destroy(); - m_tree.destroy(); -} - -template -void Column::move_assign(Column& col) -{ - ColumnBaseWithIndex::move_assign(col); - m_tree = std::move(col.m_tree); -} - -template -Allocator& Column::get_alloc() const noexcept -{ - return m_tree.get_alloc(); -} - -template -void Column::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept -{ - m_tree.set_parent(parent, ndx_in_parent); -} - -template -size_t Column::get_ndx_in_parent() const noexcept -{ - return m_tree.get_ndx_in_parent(); -} - -template -void Column::set_ndx_in_parent(size_t ndx_in_parent) noexcept -{ - ColumnBaseWithIndex::set_ndx_in_parent(ndx_in_parent); - m_tree.set_ndx_in_parent(ndx_in_parent); -} - -template -void Column::detach() noexcept -{ - m_tree.detach(); -} - -template -bool Column::is_attached() const noexcept -{ - return m_tree.is_attached(); -} - -template -ref_type Column::get_ref() const noexcept -{ - return get_root_array()->get_ref(); -} - -template -MemRef Column::get_mem() const noexcept -{ - return get_root_array()->get_mem(); -} - -template -void Column::update_from_parent(size_t old_baseline) noexcept -{ - ColumnBaseWithIndex::update_from_parent(old_baseline); - m_tree.update_from_parent(old_baseline); -} - -template -MemRef Column::clone_deep(Allocator& alloc) const -{ - return m_tree.clone_deep(alloc); -} - -template -size_t Column::size() const noexcept -{ - return m_tree.size(); -} - -template -bool Column::is_nullable() const noexcept -{ - return nullable; -} - -template -T Column::get(size_t ndx) const noexcept -{ - return m_tree.get(ndx); -} - -template -bool Column::is_null(size_t ndx) const noexcept -{ - return nullable && m_tree.is_null(ndx); -} - -template -T Column::back() const noexcept -{ - return m_tree.back(); -} - -template -ref_type Column::get_as_ref(size_t ndx) const noexcept -{ - return to_ref(get(ndx)); -} - -template -uint64_t Column::get_uint(size_t ndx) const noexcept -{ - static_assert(std::is_convertible::value, "T is not convertible to uint."); - return static_cast(get(ndx)); -} - -template -void Column::add(T value) -{ - insert(npos, std::move(value)); -} - -template -void Column::insert_without_updating_index(size_t row_ndx, T value, size_t num_rows) -{ - size_t column_size = this->size(); // Slow - bool is_append = row_ndx == column_size || row_ndx == npos; - size_t ndx_or_npos_if_append = is_append ? npos : row_ndx; - - m_tree.insert(ndx_or_npos_if_append, std::move(value), num_rows); // Throws -} - -template -void Column::insert(size_t row_ndx, T value, size_t num_rows) -{ - size_t column_size = this->size(); // Slow - bool is_append = row_ndx == column_size || row_ndx == npos; - size_t ndx_or_npos_if_append = is_append ? npos : row_ndx; - - m_tree.insert(ndx_or_npos_if_append, value, num_rows); // Throws - - if (has_search_index()) { - row_ndx = is_append ? column_size : row_ndx; - m_search_index->insert(row_ndx, value, num_rows, is_append); // Throws - } -} - -template -void Column::erase_without_updating_index(size_t row_ndx, bool is_last) -{ - m_tree.erase(row_ndx, is_last); -} - -template -void Column::erase(size_t row_ndx) -{ - REALM_ASSERT(size() >= 1); - size_t last_row_ndx = size() - 1; // Note that size() is slow - bool is_last = (row_ndx == last_row_ndx); - erase(row_ndx, is_last); // Throws -} - -template -void Column::erase(size_t row_ndx, bool is_last) -{ - size_t num_rows_to_erase = 1; - do_erase(row_ndx, num_rows_to_erase, is_last); // Throws -} - -template -void Column::move_last_over_without_updating_index(size_t row_ndx, size_t last_row_ndx) -{ - m_tree.move_last_over(row_ndx, last_row_ndx); -} - -template -void Column::move_last_over(size_t row_ndx, size_t last_row_ndx) -{ - REALM_ASSERT_3(row_ndx, <=, last_row_ndx); - REALM_ASSERT_DEBUG(last_row_ndx + 1 == size()); - - if (has_search_index()) { - // remove the value to be overwritten from index - bool is_last = true; // This tells StringIndex::erase() to not adjust subsequent indexes - m_search_index->erase(row_ndx, is_last); // Throws - - // update index to point to new location - if (row_ndx != last_row_ndx) { - T moved_value = get(last_row_ndx); - m_search_index->update_ref(moved_value, last_row_ndx, row_ndx); // Throws - } - } - - move_last_over_without_updating_index(row_ndx, last_row_ndx); -} - -template -void Column::swap_rows(size_t row_ndx_1, size_t row_ndx_2) -{ - REALM_ASSERT_3(row_ndx_1, <, size()); - REALM_ASSERT_3(row_ndx_2, <, size()); - REALM_ASSERT_DEBUG(row_ndx_1 != row_ndx_2); - - if (has_search_index()) { - T value_1 = get(row_ndx_1); - T value_2 = get(row_ndx_2); - size_t column_size = this->size(); - bool row_ndx_1_is_last = row_ndx_1 == column_size - 1; - bool row_ndx_2_is_last = row_ndx_2 == column_size - 1; - m_search_index->erase(row_ndx_1, row_ndx_1_is_last); - m_search_index->insert(row_ndx_1, value_2, 1, row_ndx_1_is_last); - - m_search_index->erase(row_ndx_2, row_ndx_2_is_last); - m_search_index->insert(row_ndx_2, value_1, 1, row_ndx_2_is_last); - } - - swap_rows_without_updating_index(row_ndx_1, row_ndx_2); -} - -template -void Column::swap_rows_without_updating_index(size_t row_ndx_1, size_t row_ndx_2) -{ - // FIXME: This can be optimized with direct getters and setters. - T value_1 = get(row_ndx_1); - T value_2 = get(row_ndx_2); - m_tree.set(row_ndx_1, value_2); - m_tree.set(row_ndx_2, value_1); -} - -template -void Column::clear_without_updating_index() -{ - m_tree.clear(); // Throws -} - -template -void Column::clear() -{ - if (has_search_index()) { - m_search_index->clear(); - } - clear_without_updating_index(); -} - -template -struct NullOrDefaultValue; -template -struct NullOrDefaultValue::value>::type> { - static T null_or_default_value(bool is_null) - { - if (is_null) { - return null::get_null_float(); - } - else { - return T{}; - } - } -}; -template -struct NullOrDefaultValue, void> { - static util::Optional null_or_default_value(bool is_null) - { - if (is_null) { - return util::none; - } - else { - return util::some(T{}); - } - } -}; -template -struct NullOrDefaultValue::value>::type> { - static T null_or_default_value(bool is_null) - { - REALM_ASSERT(!is_null); - return T{}; - } -}; - -// Implementing pure virtual method of ColumnBase. -template -void Column::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - - size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx); - T value = NullOrDefaultValue::null_or_default_value(insert_nulls); - insert(row_ndx_2, value, num_rows_to_insert); // Throws -} - -// Implementing pure virtual method of ColumnBase. -template -void Column::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(num_rows_to_erase <= prior_num_rows); - REALM_ASSERT(row_ndx <= prior_num_rows - num_rows_to_erase); - - bool is_last = (row_ndx + num_rows_to_erase == prior_num_rows); - do_erase(row_ndx, num_rows_to_erase, is_last); // Throws -} - -// Implementing pure virtual method of ColumnBase. -template -void Column::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx < prior_num_rows); - - size_t last_row_ndx = prior_num_rows - 1; - move_last_over(row_ndx, last_row_ndx); // Throws -} - -// Implementing pure virtual method of ColumnBase. -template -void Column::clear(size_t, bool) -{ - clear(); // Throws -} - - -template -size_t Column::lower_bound(T value) const noexcept -{ - if (root_is_leaf()) { - auto root = static_cast(get_root_array()); - return root->lower_bound(value); - } - return ColumnBase::lower_bound(*this, value); -} - -template -size_t Column::upper_bound(T value) const noexcept -{ - if (root_is_leaf()) { - auto root = static_cast(get_root_array()); - return root->upper_bound(value); - } - return ColumnBase::upper_bound(*this, value); -} - -// For a *sorted* Column, return first element E for which E >= target or return -1 if none -template -size_t Column::find_gte(T target, size_t start) const -{ - // fixme: slow reference implementation. See Array::find_gte for faster version - size_t ref = 0; - size_t idx; - for (idx = start; idx < size(); ++idx) { - if (get(idx) >= target) { - ref = idx; - break; - } - } - if (idx == size()) - ref = not_found; - - return ref; -} - - -template -bool Column::compare(const Column& c) const noexcept -{ - size_t n = size(); - if (c.size() != n) - return false; - for (size_t i = 0; i < n; ++i) { - bool left_is_null = is_null(i); - bool right_is_null = c.is_null(i); - if (left_is_null != right_is_null) { - return false; - } - if (!left_is_null) { - if (get(i) != c.get(i)) - return false; - } - } - return true; -} - -template -int Column::compare_values(size_t row1, size_t row2) const noexcept -{ - return ColumnBase::compare_values(this, row1, row2); -} - -template -class Column::CreateHandler : public ColumnBase::CreateHandler { -public: - CreateHandler(Array::Type leaf_type, T value, Allocator& alloc) - : m_value(value) - , m_alloc(alloc) - , m_leaf_type(leaf_type) - { - } - ref_type create_leaf(size_t size) override - { - MemRef mem = BpTree::create_leaf(m_leaf_type, size, m_value, m_alloc); // Throws - return mem.get_ref(); - } - -private: - const T m_value; - Allocator& m_alloc; - Array::Type m_leaf_type; -}; - -template -ref_type Column::create(Allocator& alloc, Array::Type leaf_type, size_t size, T value) -{ - CreateHandler handler(leaf_type, std::move(value), alloc); - return ColumnBase::create(alloc, size, handler); -} - -template -ref_type Column::write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream& out) const -{ - return m_tree.write(slice_offset, slice_size, table_size, out); -} - -template -void Column::refresh_accessor_tree(size_t new_col_ndx, const Spec& spec) -{ - m_tree.init_from_parent(); - ColumnBaseWithIndex::refresh_accessor_tree(new_col_ndx, spec); -} - -template -void Column::do_erase(size_t row_ndx, size_t num_rows_to_erase, bool is_last) -{ - if (has_search_index()) { - for (size_t i = num_rows_to_erase; i > 0; --i) { - size_t row_ndx_2 = row_ndx + i - 1; - m_search_index->erase(row_ndx_2, is_last); // Throws - } - } - for (size_t i = num_rows_to_erase; i > 0; --i) { - size_t row_ndx_2 = row_ndx + i - 1; - erase_without_updating_index(row_ndx_2, is_last); // Throws - } -} - -template -void Column::verify() const -{ -#ifdef REALM_DEBUG - m_tree.verify(); -#endif -} - -// LCOV_EXCL_START - -template -void Column::to_dot(std::ostream& out, StringData title) const -{ -#ifdef REALM_DEBUG - ref_type ref = get_root_array()->get_ref(); - out << "subgraph cluster_integer_column" << ref << " {" << std::endl; - out << " label = \"Integer column"; - if (title.size() != 0) - out << "\\n'" << title << "'"; - out << "\";" << std::endl; - tree_to_dot(out); - out << "}" << std::endl; -#else - static_cast(out); - static_cast(title); -#endif -} - -template -void Column::leaf_to_dot(MemRef leaf_mem, ArrayParent* parent, size_t ndx_in_parent, std::ostream& out) const -{ -#ifdef REALM_DEBUG - BpTree::leaf_to_dot(leaf_mem, parent, ndx_in_parent, out, get_alloc()); -#else - static_cast(leaf_mem); - static_cast(parent); - static_cast(ndx_in_parent); - static_cast(out); -#endif -} - -template -void Column::do_dump_node_structure(std::ostream& out, int level) const -{ -#ifdef REALM_DEBUG - dump_node_structure(*get_root_array(), out, level); -#else - static_cast(out); - static_cast(level); -#endif -} - -#ifdef REALM_DEBUG - -template -void Column::tree_to_dot(std::ostream& out) const -{ - ColumnBase::bptree_to_dot(get_root_array(), out); -} - - -template -MemStats Column::stats() const -{ - MemStats mem_stats; - get_root_array()->stats(mem_stats); - return mem_stats; -} - -namespace _impl { -void leaf_dumper(MemRef mem, Allocator& alloc, std::ostream& out, int level); -} - -template -void Column::dump_node_structure(const Array& root, std::ostream& out, int level) -{ - root.dump_bptree_structure(out, level, &_impl::leaf_dumper); -} - -#endif - -template -std::pair Column::get_to_dot_parent(size_t ndx_in_parent) const -{ - auto root = get_root_array(); - if (root->is_inner_bptree_node()) { - std::pair p = static_cast(root)->get_bptree_leaf(ndx_in_parent); - return std::make_pair(p.first.get_ref(), p.second); - } - else { - return std::make_pair(root->get_ref(), ndx_in_parent); - } -} - -// LCOV_EXCL_STOP ignore debug functions - - -template -ColumnRandIterator::ColumnRandIterator(const Column* src_col, size_t ndx) - : m_col_ndx(ndx) - , m_col(src_col) -{ -} - -template -bool ColumnRandIterator::operator==(const ColumnRandIterator& rhs) const -{ - return (m_col_ndx == rhs.m_col_ndx); -} - -template -bool ColumnRandIterator::operator!=(const ColumnRandIterator& rhs) const -{ - return !(*this == rhs); -} - -template -bool ColumnRandIterator::operator<(const ColumnRandIterator& rhs) const -{ - return m_col_ndx < rhs.m_col_ndx; -} - -template -bool ColumnRandIterator::operator>(const ColumnRandIterator& rhs) const -{ - return rhs < *this; -} - -template -bool ColumnRandIterator::operator<=(const ColumnRandIterator& rhs) const -{ - return !(rhs < *this); -} - -template -bool ColumnRandIterator::operator>=(const ColumnRandIterator& rhs) const -{ - return !(*this < rhs); -} - -template -ColumnRandIterator& ColumnRandIterator::operator+=(ptrdiff_t movement) -{ - m_col_ndx += movement; - return (*this); -} - -template -ColumnRandIterator& ColumnRandIterator::operator-=(ptrdiff_t movement) -{ - m_col_ndx -= movement; - return (*this); -} - -template -ColumnRandIterator& ColumnRandIterator::operator++() -{ - ++m_col_ndx; - return (*this); -} - -template -ColumnRandIterator& ColumnRandIterator::operator--() -{ - --m_col_ndx; - return (*this); -} - -template -ColumnRandIterator ColumnRandIterator::operator++(int) -{ - auto temp(*this); - ++m_col_ndx; - return temp; -} - -template -ColumnRandIterator ColumnRandIterator::operator--(int) -{ - auto temp(*this); - --m_col_ndx; - return temp; -} - -template -ColumnRandIterator ColumnRandIterator::operator+(ptrdiff_t movement) -{ - return ColumnRandIterator(m_col, m_col_ndx + movement); -} - -template -ColumnRandIterator ColumnRandIterator::operator-(ptrdiff_t movement) -{ - return ColumnRandIterator(m_col, m_col_ndx - movement); -} - -template -ptrdiff_t ColumnRandIterator::operator-(const ColumnRandIterator& other) -{ - return m_col_ndx - other.m_col_ndx; -} - -template -const ColumnDataType ColumnRandIterator::operator*() const -{ - return m_col->get(m_col_ndx); -} - -template -const ColumnDataType ColumnRandIterator::operator->() const -{ - return m_col->get(m_col_ndx); -} - -template -const ColumnDataType ColumnRandIterator::operator[](ptrdiff_t offset) const -{ - return m_col->get(m_col_ndx + offset); -} - -template -size_t ColumnRandIterator::get_col_ndx() const -{ - return m_col_ndx; -} - -template -std::ostream& operator<<(std::ostream& out, const ColumnRandIterator& it) -{ - out << "ColumnRandIterator at index: " << it.get_col_ndx(); - return out; -} - -} // namespace realm - -#endif // REALM_COLUMN_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_backlink.hpp b/Example/Pods/Realm/include/core/realm/column_backlink.hpp deleted file mode 100644 index 11ba6e5..0000000 --- a/Example/Pods/Realm/include/core/realm/column_backlink.hpp +++ /dev/null @@ -1,228 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_BACKLINK_HPP -#define REALM_COLUMN_BACKLINK_HPP - -#include - -#include -#include -#include - -namespace realm { - -/// A column of backlinks (BacklinkColumn) is a single B+-tree, and the root of -/// the column is the root of the B+-tree. All leaf nodes are single arrays of -/// type Array with the hasRefs bit set. -/// -/// The individual values in the column are either refs to Columns containing -/// the row indexes in the origin table that links to it, or in the case where -/// there is a single link, a tagged ref encoding the origin row position. -class BacklinkColumn : public IntegerColumn, public ArrayParent { -public: - BacklinkColumn(Allocator&, ref_type, size_t col_ndx = npos); - ~BacklinkColumn() noexcept override - { - } - - static ref_type create(Allocator&, size_t size = 0); - - bool has_backlinks(size_t row_ndx) const noexcept; - size_t get_backlink_count(size_t row_ndx) const noexcept; - size_t get_backlink(size_t row_ndx, size_t backlink_ndx) const noexcept; - - void add_backlink(size_t row_ndx, size_t origin_row_ndx); - void remove_one_backlink(size_t row_ndx, size_t origin_row_ndx); - void remove_all_backlinks(size_t num_rows); - void update_backlink(size_t row_ndx, size_t old_origin_row_ndx, size_t new_origin_row_ndx); - void swap_backlinks(size_t row_ndx, size_t origin_row_ndx_1, size_t origin_row_ndx_2); - - void add_row(); - - // Link origination info - Table& get_origin_table() const noexcept; - void set_origin_table(Table&) noexcept; - LinkColumnBase& get_origin_column() const noexcept; - size_t get_origin_column_index() const noexcept; - void set_origin_column(LinkColumnBase& column) noexcept; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void swap_rows(size_t, size_t) override; - void clear(size_t, bool) override; - void adj_acc_insert_rows(size_t, size_t) noexcept override; - void adj_acc_erase_row(size_t) noexcept override; - void adj_acc_move_over(size_t, size_t) noexcept override; - void adj_acc_swap_rows(size_t, size_t) noexcept override; - void adj_acc_clear_root_table() noexcept override; - void mark(int) noexcept override; - - void bump_link_origin_table_version() noexcept override; - - void cascade_break_backlinks_to(size_t row_ndx, CascadeState& state) override; - void cascade_break_backlinks_to_all_rows(size_t num_rows, CascadeState&) override; - - int compare_values(size_t, size_t) const noexcept override; - - void verify() const override; - void verify(const Table&, size_t) const override; -#ifdef REALM_DEBUG - struct VerifyPair { - size_t origin_row_ndx, target_row_ndx; - bool operator<(const VerifyPair&) const noexcept; - }; - void get_backlinks(std::vector&); // Sorts -#endif - -protected: - // ArrayParent overrides - void update_child_ref(size_t child_ndx, ref_type new_ref) override; - ref_type get_child_ref(size_t child_ndx) const noexcept override; - - std::pair get_to_dot_parent(size_t) const override; - -private: - TableRef m_origin_table; - LinkColumnBase* m_origin_column = nullptr; - - template - size_t for_each_link(size_t row_ndx, bool do_destroy, Func&& f); -}; - - -// Implementation - -inline BacklinkColumn::BacklinkColumn(Allocator& alloc, ref_type ref, size_t col_ndx) - : IntegerColumn(alloc, ref, col_ndx) // Throws -{ -} - -inline ref_type BacklinkColumn::create(Allocator& alloc, size_t size) -{ - return IntegerColumn::create(alloc, Array::type_HasRefs, size); // Throws -} - -inline bool BacklinkColumn::has_backlinks(size_t ndx) const noexcept -{ - return IntegerColumn::get(ndx) != 0; -} - -inline Table& BacklinkColumn::get_origin_table() const noexcept -{ - return *m_origin_table; -} - -inline void BacklinkColumn::set_origin_table(Table& table) noexcept -{ - REALM_ASSERT(!m_origin_table); - m_origin_table = table.get_table_ref(); -} - -inline LinkColumnBase& BacklinkColumn::get_origin_column() const noexcept -{ - return *m_origin_column; -} - -inline size_t BacklinkColumn::get_origin_column_index() const noexcept -{ - return m_origin_column ? m_origin_column->get_column_index() : npos; -} - -inline void BacklinkColumn::set_origin_column(LinkColumnBase& column) noexcept -{ - m_origin_column = &column; -} - -inline void BacklinkColumn::add_row() -{ - IntegerColumn::add(0); -} - -inline void BacklinkColumn::adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept -{ - IntegerColumn::adj_acc_insert_rows(row_ndx, num_rows); - - typedef _impl::TableFriend tf; - tf::mark(*m_origin_table); -} - -inline void BacklinkColumn::adj_acc_erase_row(size_t row_ndx) noexcept -{ - IntegerColumn::adj_acc_erase_row(row_ndx); - - typedef _impl::TableFriend tf; - tf::mark(*m_origin_table); -} - -inline void BacklinkColumn::adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept -{ - IntegerColumn::adj_acc_move_over(from_row_ndx, to_row_ndx); - - typedef _impl::TableFriend tf; - tf::mark(*m_origin_table); -} - -inline void BacklinkColumn::adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept -{ - Column::adj_acc_swap_rows(row_ndx_1, row_ndx_2); - - using tf = _impl::TableFriend; - tf::mark(*m_origin_table); -} - -inline void BacklinkColumn::adj_acc_clear_root_table() noexcept -{ - IntegerColumn::adj_acc_clear_root_table(); - - typedef _impl::TableFriend tf; - tf::mark(*m_origin_table); -} - -inline void BacklinkColumn::mark(int type) noexcept -{ - if (type & mark_LinkOrigins) { - typedef _impl::TableFriend tf; - tf::mark(*m_origin_table); - } -} - -inline void BacklinkColumn::bump_link_origin_table_version() noexcept -{ - // It is important to mark connected tables as modified. - // Also see LinkColumnBase::bump_link_origin_table_version(). - typedef _impl::TableFriend tf; - if (m_origin_table) { - bool bump_global = false; - tf::bump_version(*m_origin_table, bump_global); - } -} - -#ifdef REALM_DEBUG - -inline bool BacklinkColumn::VerifyPair::operator<(const VerifyPair& p) const noexcept -{ - return origin_row_ndx < p.origin_row_ndx; -} - -#endif // REALM_DEBUG - -} // namespace realm - -#endif // REALM_COLUMN_BACKLINK_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_binary.hpp b/Example/Pods/Realm/include/core/realm/column_binary.hpp deleted file mode 100644 index c891297..0000000 --- a/Example/Pods/Realm/include/core/realm/column_binary.hpp +++ /dev/null @@ -1,429 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_BINARY_HPP -#define REALM_COLUMN_BINARY_HPP - -#include -#include -#include - -namespace realm { - - -/// A binary column (BinaryColumn) is a single B+-tree, and the root -/// of the column is the root of the B+-tree. Leaf nodes are either of -/// type ArrayBinary (array of small blobs) or ArrayBigBlobs (array of -/// big blobs). -class BinaryColumn : public ColumnBaseSimple { -public: - typedef BinaryData value_type; - - BinaryColumn(Allocator&, ref_type, bool nullable = false, size_t column_ndx = npos); - - size_t size() const noexcept final; - bool is_empty() const noexcept - { - return size() == 0; - } - bool is_nullable() const noexcept override; - - BinaryData get(size_t ndx) const noexcept; - - /// Return data from position 'pos' and onwards. If the blob is distributed - /// across multiple arrays (if bigger than ~ 16M), you will only get data - /// from one array. 'pos' will be updated to be an index to next available - /// data. It will be 0 if no more data. - BinaryData get_at(size_t ndx, size_t& pos) const noexcept; - - bool is_null(size_t ndx) const noexcept override; - StringData get_index_data(size_t, StringIndex::StringConversionBuffer&) const noexcept final; - - void add(BinaryData value); - void set(size_t ndx, BinaryData value, bool add_zero_term = false); - void set_null(size_t ndx) override; - void insert(size_t ndx, BinaryData value); - void erase(size_t row_ndx); - void erase(size_t row_ndx, bool is_last); - void move_last_over(size_t row_ndx); - void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override; - void clear(); - size_t find_first(BinaryData value) const; - - // Requires that the specified entry was inserted as StringData. - StringData get_string(size_t ndx) const noexcept; - - void add_string(StringData value); - void set_string(size_t ndx, StringData value) override; - void insert_string(size_t ndx, StringData value); - - /// Compare two binary columns for equality. - bool compare_binary(const BinaryColumn&) const; - - int compare_values(size_t row1, size_t row2) const noexcept override; - - static ref_type create(Allocator&, size_t size, bool nullable); - - static size_t get_size_from_ref(ref_type root_ref, Allocator&) noexcept; - - // Overrriding method in ColumnBase - ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void clear(size_t, bool) override; - void update_from_parent(size_t) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - - /// In contrast to update_from_parent(), this function is able to handle - /// cases where the accessed payload data has changed. In particular, it - /// handles cases where the B+-tree switches from having one level (root is - /// a leaf node), to having multiple levels (root is an inner node). Note - /// that this is at the expense of loosing the `noexcept` guarantee. - void update_from_ref(ref_type ref); - - void verify() const override; - void to_dot(std::ostream&, StringData title) const override; - void do_dump_node_structure(std::ostream&, int) const override; - -private: - /// \param row_ndx Must be `realm::npos` if appending. - void do_insert(size_t row_ndx, BinaryData value, bool add_zero_term, size_t num_rows); - - // Called by Array::bptree_insert(). - static ref_type leaf_insert(MemRef leaf_mem, ArrayParent&, size_t ndx_in_parent, Allocator&, size_t insert_ndx, - BpTreeNode::TreeInsert& state); - - struct InsertState : BpTreeNode::TreeInsert { - bool m_add_zero_term; - }; - - class EraseLeafElem; - class CreateHandler; - class SliceHandler; - - void do_move_last_over(size_t row_ndx, size_t last_row_ndx); - void do_clear(); - - /// Root must be a leaf. Upgrades the root leaf if - /// necessary. Returns true if, and only if the root is a 'big - /// blobs' leaf upon return. - bool upgrade_root_leaf(size_t value_size); - - bool m_nullable = false; - - void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; - - friend class BpTreeNode; - friend class ColumnBase; -}; - -class BinaryIterator { -public: - BinaryIterator() - { - } - // TODO: When WriteLogCollector is removed, there is no need for this - BinaryIterator(BinaryData binary) - : m_binary(binary) - { - } - - BinaryIterator(BinaryColumn* col, size_t ndx) - : m_binary_col(col) - , m_ndx(ndx) - { - } - - BinaryData get_next() noexcept - { - if (!end_of_data) { - if (m_binary_col) { - BinaryData ret = m_binary_col->get_at(m_ndx, m_pos); - end_of_data = (m_pos == 0); - return ret; - } - else if (!m_binary.is_null()) { - end_of_data = true; - return m_binary; - } - } - return {}; - } - -private: - bool end_of_data = false; - BinaryColumn* m_binary_col = nullptr; - size_t m_ndx = 0; - size_t m_pos = 0; - BinaryData m_binary; -}; - - -// Implementation - -// LCOV_EXCL_START -inline StringData BinaryColumn::get_index_data(size_t, StringIndex::StringConversionBuffer&) const noexcept -{ - REALM_ASSERT(false && "Index not implemented for BinaryColumn."); - REALM_UNREACHABLE(); -} -// LCOV_EXCL_STOP - -inline size_t BinaryColumn::size() const noexcept -{ - if (root_is_leaf()) { - bool is_big = m_array->get_context_flag(); - if (!is_big) { - // Small blobs root leaf - ArrayBinary* leaf = static_cast(m_array.get()); - return leaf->size(); - } - // Big blobs root leaf - ArrayBigBlobs* leaf = static_cast(m_array.get()); - return leaf->size(); - } - // Non-leaf root - return static_cast(m_array.get())->get_bptree_size(); -} - -inline bool BinaryColumn::is_nullable() const noexcept -{ - return m_nullable; -} - -inline void BinaryColumn::update_from_parent(size_t old_baseline) noexcept -{ - if (root_is_leaf()) { - bool is_big = m_array->get_context_flag(); - if (!is_big) { - // Small blobs root leaf - REALM_ASSERT(dynamic_cast(m_array.get())); - ArrayBinary* leaf = static_cast(m_array.get()); - leaf->update_from_parent(old_baseline); - return; - } - // Big blobs root leaf - REALM_ASSERT(dynamic_cast(m_array.get())); - ArrayBigBlobs* leaf = static_cast(m_array.get()); - leaf->update_from_parent(old_baseline); - return; - } - // Non-leaf root - m_array->update_from_parent(old_baseline); -} - -inline BinaryData BinaryColumn::get(size_t ndx) const noexcept -{ - REALM_ASSERT_DEBUG(ndx < size()); - if (root_is_leaf()) { - bool is_big = m_array->get_context_flag(); - BinaryData ret; - if (!is_big) { - // Small blobs root leaf - ArrayBinary* leaf = static_cast(m_array.get()); - ret = leaf->get(ndx); - } - else { - // Big blobs root leaf - ArrayBigBlobs* leaf = static_cast(m_array.get()); - ret = leaf->get(ndx); - } - if (!m_nullable && ret.is_null()) - return BinaryData("", 0); // return empty string (non-null) - return ret; - } - - // Non-leaf root - std::pair p = static_cast(m_array.get())->get_bptree_leaf(ndx); - const char* leaf_header = p.first.get_addr(); - size_t ndx_in_leaf = p.second; - Allocator& alloc = m_array->get_alloc(); - bool is_big = Array::get_context_flag_from_header(leaf_header); - if (!is_big) { - // Small blobs - return ArrayBinary::get(leaf_header, ndx_in_leaf, alloc); - } - // Big blobs - return ArrayBigBlobs::get(leaf_header, ndx_in_leaf, alloc); -} - -inline bool BinaryColumn::is_null(size_t ndx) const noexcept -{ - return m_nullable && get(ndx).is_null(); -} - -inline StringData BinaryColumn::get_string(size_t ndx) const noexcept -{ - BinaryData bin = get(ndx); - REALM_ASSERT_3(0, <, bin.size()); - return StringData(bin.data(), bin.size() - 1); -} - -inline void BinaryColumn::set_string(size_t ndx, StringData value) -{ - if (value.is_null() && !m_nullable) - throw LogicError(LogicError::column_not_nullable); - - BinaryData bin(value.data(), value.size()); - bool add_zero_term = true; - set(ndx, bin, add_zero_term); -} - -inline void BinaryColumn::add(BinaryData value) -{ - if (value.is_null() && !m_nullable) - throw LogicError(LogicError::column_not_nullable); - - size_t row_ndx = realm::npos; - bool add_zero_term = false; - size_t num_rows = 1; - do_insert(row_ndx, value, add_zero_term, num_rows); // Throws -} - -inline void BinaryColumn::insert(size_t row_ndx, BinaryData value) -{ - if (value.is_null() && !m_nullable) - throw LogicError(LogicError::column_not_nullable); - - size_t column_size = this->size(); // Slow - REALM_ASSERT_3(row_ndx, <=, column_size); - size_t row_ndx_2 = row_ndx == column_size ? realm::npos : row_ndx; - bool add_zero_term = false; - size_t num_rows = 1; - do_insert(row_ndx_2, value, add_zero_term, num_rows); // Throws -} - -inline void BinaryColumn::set_null(size_t row_ndx) -{ - set(row_ndx, BinaryData{}); -} - -inline size_t BinaryColumn::find_first(BinaryData value) const -{ - for (size_t t = 0; t < size(); t++) - if (get(t) == value) - return t; - - return not_found; -} - - -inline void BinaryColumn::erase(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - bool is_last = row_ndx == last_row_ndx; - erase(row_ndx, is_last); // Throws -} - -inline void BinaryColumn::move_last_over(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -inline void BinaryColumn::clear() -{ - do_clear(); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void BinaryColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - REALM_ASSERT(!insert_nulls || m_nullable); - - size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx); - BinaryData value = m_nullable ? BinaryData() : BinaryData("", 0); - bool add_zero_term = false; - do_insert(row_ndx_2, value, add_zero_term, num_rows_to_insert); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void BinaryColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(num_rows_to_erase <= prior_num_rows); - REALM_ASSERT(row_ndx <= prior_num_rows - num_rows_to_erase); - - bool is_last = (row_ndx + num_rows_to_erase == prior_num_rows); - for (size_t i = num_rows_to_erase; i > 0; --i) { - size_t row_ndx_2 = row_ndx + i - 1; - erase(row_ndx_2, is_last); // Throws - } -} - -// Implementing pure virtual method of ColumnBase. -inline void BinaryColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx < prior_num_rows); - - size_t last_row_ndx = prior_num_rows - 1; - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void BinaryColumn::clear(size_t, bool) -{ - do_clear(); // Throws -} - -inline void BinaryColumn::add_string(StringData value) -{ - size_t row_ndx = realm::npos; - BinaryData value_2(value.data(), value.size()); - bool add_zero_term = true; - size_t num_rows = 1; - do_insert(row_ndx, value_2, add_zero_term, num_rows); // Throws -} - -inline void BinaryColumn::insert_string(size_t row_ndx, StringData value) -{ - size_t column_size = this->size(); // Slow - REALM_ASSERT_3(row_ndx, <=, column_size); - size_t row_ndx_2 = row_ndx == column_size ? realm::npos : row_ndx; - BinaryData value_2(value.data(), value.size()); - bool add_zero_term = false; - size_t num_rows = 1; - do_insert(row_ndx_2, value_2, add_zero_term, num_rows); // Throws -} - -inline size_t BinaryColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept -{ - const char* root_header = alloc.translate(root_ref); - bool root_is_leaf = !Array::get_is_inner_bptree_node_from_header(root_header); - if (root_is_leaf) { - bool is_big = Array::get_context_flag_from_header(root_header); - if (!is_big) { - // Small blobs leaf - return ArrayBinary::get_size_from_header(root_header, alloc); - } - // Big blobs leaf - return ArrayBigBlobs::get_size_from_header(root_header); - } - return BpTreeNode::get_bptree_size_from_header(root_header); -} - - -} // namespace realm - -#endif // REALM_COLUMN_BINARY_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_fwd.hpp b/Example/Pods/Realm/include/core/realm/column_fwd.hpp deleted file mode 100644 index 1eecf01..0000000 --- a/Example/Pods/Realm/include/core/realm/column_fwd.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_FWD_HPP -#define REALM_COLUMN_FWD_HPP - -#include - -namespace realm { - -// Regular classes -class ColumnBase; -class StringColumn; -class StringEnumColumn; -class BinaryColumn; -class SubtableColumn; -class MixedColumn; -class LinkColumn; -class LinkListColumn; - -// Templated classes -template -class Column; -template -class BasicColumn; -template -class ColumnRandIterator; - -namespace util { -template -class Optional; -} - -// Shortcuts, aka typedefs. -using IntegerColumn = Column; -using IntNullColumn = Column>; -using DoubleColumn = Column; -using FloatColumn = Column; -using IntegerColumnIterator = ColumnRandIterator; -} // namespace realm - -#endif // REALM_COLUMN_FWD_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_link.hpp b/Example/Pods/Realm/include/core/realm/column_link.hpp deleted file mode 100644 index 18471bb..0000000 --- a/Example/Pods/Realm/include/core/realm/column_link.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_LINK_HPP -#define REALM_COLUMN_LINK_HPP - -#include -#include -#include - -namespace realm { - -/// A link column is an extension of an integer column (Column) and maintains -/// its node structure. -/// -/// The individual values in a link column are indexes of rows in the target -/// table (offset with one to allow zero to indicate null links.) The target -/// table is specified by the table descriptor. -class LinkColumn : public LinkColumnBase { -public: - using LinkColumnBase::LinkColumnBase; - ~LinkColumn() noexcept override; - - static ref_type create(Allocator&, size_t size = 0); - - bool is_nullable() const noexcept override; - - //@{ - - /// is_null_link() is shorthand for `get_link() == realm::npos`, - /// nullify_link() is shorthand foe `set_link(realm::npos)`, and - /// insert_null_link() is shorthand for - /// `insert_link(realm::npos)`. set_link() returns the original link, with - /// `realm::npos` indicating that it was null. - - size_t get_link(size_t row_ndx) const noexcept; - bool is_null(size_t row_ndx) const noexcept override; - bool is_null_link(size_t row_ndx) const noexcept; - size_t set_link(size_t row_ndx, size_t target_row_ndx); - void set_null(size_t row_ndx) override; - void nullify_link(size_t row_ndx); - void insert_link(size_t row_ndx, size_t target_row_ndx); - void insert_null_link(size_t row_ndx); - - //@} - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void swap_rows(size_t, size_t) override; - void clear(size_t, bool) override; - void cascade_break_backlinks_to(size_t, CascadeState&) override; - void cascade_break_backlinks_to_all_rows(size_t, CascadeState&) override; - - void verify(const Table&, size_t) const override; - -protected: - friend class BacklinkColumn; - void do_nullify_link(size_t row_ndx, size_t old_target_row_ndx) override; - void do_update_link(size_t row_ndx, size_t old_target_row_ndx, size_t new_target_row_ndx) override; - void do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) override; - -private: - void remove_backlinks(size_t row_ndx); -}; - - -// Implementation - -inline LinkColumn::~LinkColumn() noexcept -{ -} - -inline bool LinkColumn::is_nullable() const noexcept -{ - return true; -} - -inline ref_type LinkColumn::create(Allocator& alloc, size_t size) -{ - return IntegerColumn::create(alloc, Array::type_Normal, size); // Throws -} - -inline bool LinkColumn::is_null(size_t row_ndx) const noexcept -{ - // Null is represented by zero - return LinkColumnBase::get(row_ndx) == 0; -} - -inline size_t LinkColumn::get_link(size_t row_ndx) const noexcept -{ - // Map zero to realm::npos, and `n+1` to `n`, where `n` is a target row index. - return to_size_t(LinkColumnBase::get(row_ndx)) - size_t(1); -} - -inline bool LinkColumn::is_null_link(size_t row_ndx) const noexcept -{ - return is_null(row_ndx); -} - -inline size_t LinkColumn::set_link(size_t row_ndx, size_t target_row_ndx) -{ - int_fast64_t old_value = LinkColumnBase::get(row_ndx); - size_t old_target_row_ndx = to_size_t(old_value) - size_t(1); - if (old_value != 0) - m_backlink_column->remove_one_backlink(old_target_row_ndx, row_ndx); // Throws - - int_fast64_t new_value = int_fast64_t(size_t(1) + target_row_ndx); - LinkColumnBase::set(row_ndx, new_value); // Throws - - if (target_row_ndx != realm::npos) - m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws - - return old_target_row_ndx; -} - -inline void LinkColumn::set_null(size_t row_ndx) -{ - set_link(row_ndx, realm::npos); // Throws -} - -inline void LinkColumn::nullify_link(size_t row_ndx) -{ - set_null(row_ndx); // Throws -} - -inline void LinkColumn::insert_link(size_t row_ndx, size_t target_row_ndx) -{ - int_fast64_t value = int_fast64_t(size_t(1) + target_row_ndx); - LinkColumnBase::insert(row_ndx, value); // Throws - - if (target_row_ndx != realm::npos) - m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws -} - -inline void LinkColumn::insert_null_link(size_t row_ndx) -{ - insert_link(row_ndx, realm::npos); // Throws -} - -inline void LinkColumn::do_update_link(size_t row_ndx, size_t, size_t new_target_row_ndx) -{ - // Row pos is offset by one, to allow null refs - LinkColumnBase::set(row_ndx, new_target_row_ndx + 1); -} - -inline void LinkColumn::do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) -{ - // Row pos is offset by one, to allow null refs - ++target_row_ndx_1; - ++target_row_ndx_2; - - uint64_t value = LinkColumnBase::get_uint(row_ndx); - if (value == target_row_ndx_1) { - LinkColumnBase::set_uint(row_ndx, target_row_ndx_2); - } - else if (value == target_row_ndx_2) { - LinkColumnBase::set_uint(row_ndx, target_row_ndx_1); - } -} - -} // namespace realm - -#endif // REALM_COLUMN_LINK_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_linkbase.hpp b/Example/Pods/Realm/include/core/realm/column_linkbase.hpp deleted file mode 100644 index cff46b2..0000000 --- a/Example/Pods/Realm/include/core/realm/column_linkbase.hpp +++ /dev/null @@ -1,197 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_LINKBASE_HPP -#define REALM_COLUMN_LINKBASE_HPP - -#include - -namespace realm { - -class BacklinkColumn; -class Table; - -// Abstract base class for columns containing links -class LinkColumnBase : public IntegerColumn { -public: - // Create unattached root array aaccessor. - LinkColumnBase(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx); - ~LinkColumnBase() noexcept override; - - bool is_nullable() const noexcept override = 0; - void set_null(size_t) override = 0; - bool is_null(size_t) const noexcept override = 0; - - bool supports_search_index() const noexcept final - { - return false; - } - StringIndex* create_search_index() override; - - bool get_weak_links() const noexcept; - void set_weak_links(bool) noexcept; - - Table& get_target_table() const noexcept; - void set_target_table(Table&) noexcept; - BacklinkColumn& get_backlink_column() const noexcept; - void set_backlink_column(BacklinkColumn&) noexcept; - - void swap_rows(size_t, size_t) override = 0; - - virtual void do_nullify_link(size_t row_ndx, size_t old_target_row_ndx) = 0; - virtual void do_update_link(size_t row_ndx, size_t old_target_row_ndx, size_t new_target_row_ndx) = 0; - virtual void do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) = 0; - - void adj_acc_insert_rows(size_t, size_t) noexcept override; - void adj_acc_erase_row(size_t) noexcept override; - void adj_acc_move_over(size_t, size_t) noexcept override; - void adj_acc_swap_rows(size_t, size_t) noexcept override; - void adj_acc_clear_root_table() noexcept override; - void mark(int) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - void bump_link_origin_table_version() noexcept override; - - void verify(const Table&, size_t) const override; - using IntegerColumn::verify; - -protected: - // A pointer to the table that this column is part of. - Table* const m_table; - - TableRef m_target_table; - BacklinkColumn* m_backlink_column = nullptr; - bool m_weak_links = false; // True if these links are weak (not strong) - - /// Call Table::cascade_break_backlinks_to() for the specified target row if - /// it is not already in \a state.rows, and the number of strong links to it - /// has dropped to zero. - void check_cascade_break_backlinks_to(size_t target_table_ndx, size_t target_row_ndx, CascadeState& state); -}; - - -// Implementation - -inline LinkColumnBase::LinkColumnBase(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx) - : IntegerColumn(alloc, ref, column_ndx) // Throws - , m_table(table) -{ -} - -inline LinkColumnBase::~LinkColumnBase() noexcept -{ -} - -inline StringIndex* LinkColumnBase::create_search_index() -{ - return nullptr; -} - -inline bool LinkColumnBase::get_weak_links() const noexcept -{ - return m_weak_links; -} - -inline void LinkColumnBase::set_weak_links(bool value) noexcept -{ - m_weak_links = value; -} - -inline Table& LinkColumnBase::get_target_table() const noexcept -{ - return *m_target_table; -} - -inline void LinkColumnBase::set_target_table(Table& table) noexcept -{ - REALM_ASSERT(!m_target_table); - m_target_table = table.get_table_ref(); -} - -inline BacklinkColumn& LinkColumnBase::get_backlink_column() const noexcept -{ - return *m_backlink_column; -} - -inline void LinkColumnBase::set_backlink_column(BacklinkColumn& column) noexcept -{ - m_backlink_column = &column; -} - -inline void LinkColumnBase::adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept -{ - IntegerColumn::adj_acc_insert_rows(row_ndx, num_rows); - - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); -} - -inline void LinkColumnBase::adj_acc_erase_row(size_t row_ndx) noexcept -{ - IntegerColumn::adj_acc_erase_row(row_ndx); - - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); -} - -inline void LinkColumnBase::adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept -{ - IntegerColumn::adj_acc_move_over(from_row_ndx, to_row_ndx); - - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); -} - -inline void LinkColumnBase::adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept -{ - IntegerColumn::adj_acc_swap_rows(row_ndx_1, row_ndx_2); - - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); -} - -inline void LinkColumnBase::adj_acc_clear_root_table() noexcept -{ - IntegerColumn::adj_acc_clear_root_table(); - - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); -} - -inline void LinkColumnBase::mark(int type) noexcept -{ - if (type & mark_LinkTargets) { - typedef _impl::TableFriend tf; - tf::mark(*m_target_table); - } -} - -inline void LinkColumnBase::bump_link_origin_table_version() noexcept -{ - // It is important to mark connected tables as modified. - // Also see BacklinkColumn::bump_link_origin_table_version(). - typedef _impl::TableFriend tf; - if (m_target_table) { - bool bump_global = false; - tf::bump_version(*m_target_table, bump_global); - } -} - - -} // namespace realm - -#endif // REALM_COLUMN_LINKBASE_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_linklist.hpp b/Example/Pods/Realm/include/core/realm/column_linklist.hpp deleted file mode 100644 index 445066e..0000000 --- a/Example/Pods/Realm/include/core/realm/column_linklist.hpp +++ /dev/null @@ -1,243 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_LINKLIST_HPP -#define REALM_COLUMN_LINKLIST_HPP - -#include -#include - -#include -#include -#include -#include -#include - -namespace realm { - -namespace _impl { -class TransactLogConvenientEncoder; -} - - -/// A column of link lists (LinkListColumn) is a single B+-tree, and the root of -/// the column is the root of the B+-tree. All leaf nodes are single arrays of -/// type Array with the hasRefs bit set. -/// -/// The individual values in the column are either refs to Columns containing the -/// row positions in the target table, or in the case where they are empty, a zero -/// ref. -class LinkListColumn : public LinkColumnBase, public ArrayParent { -public: - using LinkColumnBase::LinkColumnBase; - LinkListColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx); - ~LinkListColumn() noexcept override; - - static ref_type create(Allocator&, size_t size = 0); - - bool is_nullable() const noexcept final; - - bool has_links(size_t row_ndx) const noexcept; - size_t get_link_count(size_t row_ndx) const noexcept; - - ConstLinkViewRef get(size_t row_ndx) const; - LinkViewRef get(size_t row_ndx); - - bool is_null(size_t row_ndx) const noexcept final; - void set_null(size_t row_ndx) final; - - /// Compare two columns for equality. - bool compare_link_list(const LinkListColumn&) const; - - void to_json_row(size_t row_ndx, std::ostream& out) const; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void swap_rows(size_t, size_t) override; - void clear(size_t, bool) override; - void cascade_break_backlinks_to(size_t, CascadeState&) override; - void cascade_break_backlinks_to_all_rows(size_t, CascadeState&) override; - void update_from_parent(size_t) noexcept override; - void adj_acc_clear_root_table() noexcept override; - void adj_acc_insert_rows(size_t, size_t) noexcept override; - void adj_acc_erase_row(size_t) noexcept override; - void adj_acc_move_over(size_t, size_t) noexcept override; - void adj_acc_swap_rows(size_t, size_t) noexcept override; - void adj_acc_merge_rows(size_t, size_t) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - - void verify() const override; - void verify(const Table&, size_t) const override; - -protected: - void do_discard_child_accessors() noexcept override; - -private: - struct list_entry { - size_t m_row_ndx; - std::weak_ptr m_list; - bool operator<(const list_entry& other) const - { - return m_row_ndx < other.m_row_ndx; - } - }; - - // The accessors stored in `m_list_accessors` are sorted by their row index. - // When a LinkList accessor is destroyed because the last shared_ptr pointing - // to it dies, its entry is implicitly replaced by a tombstone (an entry with - // an empty `m_list`). These tombstones are pruned at a later time by - // `prune_list_accessor_tombstones`. This is done to amortize the O(n) cost - // of `std::vector::erase` that would otherwise be incurred each time an - // accessor is removed. - mutable std::vector m_list_accessors; - mutable std::atomic m_list_accessors_contains_tombstones; - - std::shared_ptr get_ptr(size_t row_ndx) const; - - void do_nullify_link(size_t row_ndx, size_t old_target_row_ndx) override; - void do_update_link(size_t row_ndx, size_t old_target_row_ndx, size_t new_target_row_ndx) override; - void do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) override; - - void unregister_linkview(); - ref_type get_row_ref(size_t row_ndx) const noexcept; - void set_row_ref(size_t row_ndx, ref_type new_ref); - void add_backlink(size_t target_row, size_t source_row); - void remove_backlink(size_t target_row, size_t source_row); - - // ArrayParent overrides - void update_child_ref(size_t child_ndx, ref_type new_ref) override; - ref_type get_child_ref(size_t child_ndx) const noexcept override; - - // These helpers are needed because of the way the B+-tree of links is - // traversed in cascade_break_backlinks_to() and - // cascade_break_backlinks_to_all_rows(). - void cascade_break_backlinks_to__leaf(size_t row_ndx, const Array& link_list_leaf, CascadeState&); - void cascade_break_backlinks_to_all_rows__leaf(const Array& link_list_leaf, CascadeState&); - - void discard_child_accessors() noexcept; - - template - void adj_insert_rows(size_t row_ndx, size_t num_rows_inserted) noexcept; - - template - void adj_erase_rows(size_t row_ndx, size_t num_rows_erased) noexcept; - - template - void adj_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; - - template - void adj_swap(size_t row_ndx_1, size_t row_ndx_2) noexcept; - - void prune_list_accessor_tombstones() noexcept; - void validate_list_accessors() const noexcept; - - std::pair get_to_dot_parent(size_t) const override; - - friend class BacklinkColumn; - friend class LinkView; - friend class _impl::TransactLogConvenientEncoder; -}; - - -// Implementation - -inline LinkListColumn::LinkListColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx) - : LinkColumnBase(alloc, ref, table, column_ndx) -{ - m_list_accessors_contains_tombstones.store(false); -} - -inline LinkListColumn::~LinkListColumn() noexcept -{ - discard_child_accessors(); -} - -inline ref_type LinkListColumn::create(Allocator& alloc, size_t size) -{ - return IntegerColumn::create(alloc, Array::type_HasRefs, size); // Throws -} - -inline bool LinkListColumn::is_nullable() const noexcept -{ - return false; -} - -inline bool LinkListColumn::has_links(size_t row_ndx) const noexcept -{ - ref_type ref = LinkColumnBase::get_as_ref(row_ndx); - return (ref != 0); -} - -inline size_t LinkListColumn::get_link_count(size_t row_ndx) const noexcept -{ - ref_type ref = LinkColumnBase::get_as_ref(row_ndx); - if (ref == 0) - return 0; - return ColumnBase::get_size_from_ref(ref, get_alloc()); -} - -inline ConstLinkViewRef LinkListColumn::get(size_t row_ndx) const -{ - return get_ptr(row_ndx); -} - -inline LinkViewRef LinkListColumn::get(size_t row_ndx) -{ - return get_ptr(row_ndx); -} - -inline bool LinkListColumn::is_null(size_t) const noexcept -{ - return false; -} - -inline void LinkListColumn::set_null(size_t) -{ - throw LogicError{LogicError::column_not_nullable}; -} - -inline void LinkListColumn::do_discard_child_accessors() noexcept -{ - discard_child_accessors(); -} - -inline ref_type LinkListColumn::get_row_ref(size_t row_ndx) const noexcept -{ - return LinkColumnBase::get_as_ref(row_ndx); -} - -inline void LinkListColumn::set_row_ref(size_t row_ndx, ref_type new_ref) -{ - LinkColumnBase::set(row_ndx, new_ref); // Throws -} - -inline void LinkListColumn::add_backlink(size_t target_row, size_t source_row) -{ - m_backlink_column->add_backlink(target_row, source_row); // Throws -} - -inline void LinkListColumn::remove_backlink(size_t target_row, size_t source_row) -{ - m_backlink_column->remove_one_backlink(target_row, source_row); // Throws -} - - -} // namespace realm - -#endif // REALM_COLUMN_LINKLIST_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_mixed.hpp b/Example/Pods/Realm/include/core/realm/column_mixed.hpp deleted file mode 100644 index 326edad..0000000 --- a/Example/Pods/Realm/include/core/realm/column_mixed.hpp +++ /dev/null @@ -1,268 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_MIXED_HPP -#define REALM_COLUMN_MIXED_HPP - -#include - -#include -#include -#include -#include -#include -#include - - -namespace realm { - - -// Pre-declarations -class BinaryColumn; - - -/// A mixed column (MixedColumn) is composed of three subcolumns. The first -/// subcolumn is an integer column (Column) and stores value types. The second -/// one stores values and is a subtable parent column (SubtableColumnBase), -/// which is a subclass of an integer column (Column). The last one is a binary -/// column (BinaryColumn) and stores additional data for values of type string -/// or binary data. The last subcolumn is optional. The root of a mixed column -/// is an array node of type Array that stores the root refs of the subcolumns. -class MixedColumn : public ColumnBaseSimple { -public: - /// Create a mixed column wrapper and attach it to a preexisting - /// underlying structure of arrays. - /// - /// \param alloc The memory allocator to change the underlying - /// structure in memory. - /// - /// \param ref The memory reference of the MixedColumn for which - /// this accessor should be creator for. - /// - /// \param table If this column is used as part of a table you - /// must pass a pointer to that table. Otherwise you must pass - /// null - /// - /// \param column_ndx If this column is used as part of a table - /// you must pass the logical index of the column within that - /// table. Otherwise you should pass zero. - MixedColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx); - - ~MixedColumn() noexcept override; - - DataType get_type(size_t ndx) const noexcept; - size_t size() const noexcept final - { - return m_types->size(); - } - bool is_empty() const noexcept - { - return size() == 0; - } - - int64_t get_int(size_t ndx) const noexcept; - bool get_bool(size_t ndx) const noexcept; - OldDateTime get_olddatetime(size_t ndx) const noexcept; - Timestamp get_timestamp(size_t ndx) const noexcept; - float get_float(size_t ndx) const noexcept; - double get_double(size_t ndx) const noexcept; - StringData get_string(size_t ndx) const noexcept; - BinaryData get_binary(size_t ndx) const noexcept; - StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept override; - - /// The returned array ref is zero if the specified row does not - /// contain a subtable. - ref_type get_subtable_ref(size_t row_ndx) const noexcept; - - /// The returned size is zero if the specified row does not - /// contain a subtable. - size_t get_subtable_size(size_t row_ndx) const noexcept; - - Table* get_subtable_accessor(size_t row_ndx) const noexcept override; - - void discard_subtable_accessor(size_t row_ndx) noexcept override; - - /// If the value at the specified index is a subtable, return a - /// pointer to that accessor for that subtable. Otherwise return - /// null. The accessor will be created if it does not already - /// exist. - /// - /// The returned table pointer must **always** end up being - /// wrapped in some instantiation of BasicTableRef<>. - Table* get_subtable_ptr(size_t row_ndx); - - const Table* get_subtable_ptr(size_t subtable_ndx) const; - - void set_int(size_t ndx, int64_t value); - void set_bool(size_t ndx, bool value); - void set_olddatetime(size_t ndx, OldDateTime value); - void set_timestamp(size_t ndx, Timestamp value); - void set_float(size_t ndx, float value); - void set_double(size_t ndx, double value); - void set_string(size_t ndx, StringData value) override; - void set_binary(size_t ndx, BinaryData value); - void set_subtable(size_t ndx, const Table* value); - - void insert_int(size_t ndx, int_fast64_t value); - void insert_bool(size_t ndx, bool value); - void insert_olddatetime(size_t ndx, OldDateTime value); - void insert_timestamp(size_t ndx, Timestamp value); - void insert_float(size_t ndx, float value); - void insert_double(size_t ndx, double value); - void insert_string(size_t ndx, StringData value); - void insert_binary(size_t ndx, BinaryData value); - void insert_subtable(size_t ndx, const Table* value); - - void erase(size_t row_ndx); - void move_last_over(size_t row_ndx); - void clear(); - - /// Compare two mixed columns for equality. - bool compare_mixed(const MixedColumn&) const; - - int compare_values(size_t row1, size_t row2) const noexcept override; - - void discard_child_accessors() noexcept; - - static ref_type create(Allocator&, size_t size = 0); - - static size_t get_size_from_ref(ref_type root_ref, Allocator&) noexcept; - - // Overriding method in ColumnBase - ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void swap_rows(size_t, size_t) override; - void clear(size_t, bool) override; - void update_from_parent(size_t) noexcept override; - void adj_acc_insert_rows(size_t, size_t) noexcept override; - void adj_acc_erase_row(size_t) noexcept override; - void adj_acc_move_over(size_t, size_t) noexcept override; - void adj_acc_swap_rows(size_t, size_t) noexcept override; - void adj_acc_clear_root_table() noexcept override; - void mark(int) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - - void verify() const override; - void verify(const Table&, size_t) const override; - void to_dot(std::ostream&, StringData title) const override; - void do_dump_node_structure(std::ostream&, int) const override; - -private: - enum MixedColType { - // NOTE: below numbers must be kept in sync with ColumnType - // Column types used in Mixed - mixcol_Int = 0, - mixcol_Bool = 1, - mixcol_String = 2, - // 3, used for STRING_ENUM in ColumnType - mixcol_Binary = 4, - mixcol_Table = 5, - mixcol_Mixed = 6, - mixcol_OldDateTime = 7, - mixcol_Timestamp = 8, - mixcol_Float = 9, - mixcol_Double = 10, // Positive Double - mixcol_DoubleNeg = 11, // Negative Double - mixcol_IntNeg = 12 // Negative Integers - }; - - class RefsColumn; - - /// Stores the MixedColType of each value at the given index. For - /// values that uses all 64 bits, the type also encodes the sign - /// bit by having distinct types for positive negative values. - std::unique_ptr m_types; - - /// Stores the data for each entry. For a subtable, the stored - /// value is the ref of the subtable. For string, binary data, - /// the stored value is an index within `m_binary_data`. Likewise, - /// for timestamp, an index into `m_timestamp` is stored. For other - /// types the stored value is itself. Since we only have 63 bits - /// available for a non-ref value, the sign of numeric values is - /// encoded as part of the type in `m_types`. - std::unique_ptr m_data; - - /// For string and binary data types, the bytes are stored here. - std::unique_ptr m_binary_data; - - /// Timestamps are stored here. - std::unique_ptr m_timestamp_data; - - void do_erase(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows); - void do_move_last_over(size_t row_ndx, size_t prior_num_rows); - void do_swap_rows(size_t, size_t); - void do_clear(size_t num_rows); - - void create(Allocator&, ref_type, Table*, size_t column_ndx); - void ensure_binary_data_column(); - void ensure_timestamp_column(); - - MixedColType clear_value(size_t ndx, MixedColType new_type); // Returns old type - void clear_value_and_discard_subtab_acc(size_t ndx, MixedColType new_type); - - // Get/set/insert 64-bit values in m_data/m_types - int64_t get_value(size_t ndx) const noexcept; - void set_value(size_t ndx, int64_t value, MixedColType); - void set_int64(size_t ndx, int64_t value, MixedColType pos_type, MixedColType neg_type); - - void insert_value(size_t row_ndx, int_fast64_t types_value, int_fast64_t data_value); - void insert_int(size_t ndx, int_fast64_t value, MixedColType type); - void insert_pos_neg(size_t ndx, int_fast64_t value, MixedColType pos_type, MixedColType neg_type); - - void do_discard_child_accessors() noexcept override; - -#ifdef REALM_DEBUG - void do_verify(const Table*, size_t col_ndx) const; -#endif - void leaf_to_dot(MemRef, ArrayParent*, size_t, std::ostream&) const override; -}; - -// LCOV_EXCL_START -inline StringData MixedColumn::get_index_data(size_t, StringIndex::StringConversionBuffer&) const noexcept -{ - REALM_ASSERT(false && "Index not supported for MixedColumn yet."); - REALM_UNREACHABLE(); - return {}; -} -// LCOV_EXCL_STOP - - -class MixedColumn::RefsColumn : public SubtableColumnBase { -public: - RefsColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx); - ~RefsColumn() noexcept override; - - using SubtableColumnBase::get_subtable_ptr; - - void refresh_accessor_tree(size_t, const Spec&) override; - - friend class MixedColumn; -}; - - -} // namespace realm - - -// Implementation -#include - - -#endif // REALM_COLUMN_MIXED_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_mixed_tpl.hpp b/Example/Pods/Realm/include/core/realm/column_mixed_tpl.hpp deleted file mode 100644 index ca5d4d4..0000000 --- a/Example/Pods/Realm/include/core/realm/column_mixed_tpl.hpp +++ /dev/null @@ -1,505 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -namespace realm { - -inline MixedColumn::MixedColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx) - : ColumnBaseSimple(column_ndx) -{ - create(alloc, ref, table, column_ndx); -} - -inline void MixedColumn::adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept -{ - m_data->adj_acc_insert_rows(row_ndx, num_rows); -} - -inline void MixedColumn::adj_acc_erase_row(size_t row_ndx) noexcept -{ - m_data->adj_acc_erase_row(row_ndx); -} - -inline void MixedColumn::adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept -{ - m_data->adj_acc_swap_rows(row_ndx_1, row_ndx_2); -} - -inline void MixedColumn::adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept -{ - m_data->adj_acc_move_over(from_row_ndx, to_row_ndx); -} - -inline void MixedColumn::adj_acc_clear_root_table() noexcept -{ - m_data->adj_acc_clear_root_table(); -} - -inline ref_type MixedColumn::get_subtable_ref(size_t row_ndx) const noexcept -{ - REALM_ASSERT_3(row_ndx, <, m_types->size()); - if (m_types->get(row_ndx) != type_Table) - return 0; - return m_data->get_as_ref(row_ndx); -} - -inline size_t MixedColumn::get_subtable_size(size_t row_ndx) const noexcept -{ - ref_type top_ref = get_subtable_ref(row_ndx); - if (top_ref == 0) - return 0; - return _impl::TableFriend::get_size_from_ref(top_ref, m_data->get_alloc()); -} - -inline Table* MixedColumn::get_subtable_accessor(size_t row_ndx) const noexcept -{ - return m_data->get_subtable_accessor(row_ndx); -} - -inline void MixedColumn::discard_subtable_accessor(size_t row_ndx) noexcept -{ - m_data->discard_subtable_accessor(row_ndx); -} - -inline Table* MixedColumn::get_subtable_ptr(size_t row_ndx) -{ - REALM_ASSERT_3(row_ndx, <, m_types->size()); - if (m_types->get(row_ndx) != type_Table) - return 0; - return m_data->get_subtable_ptr(row_ndx); // Throws -} - -inline const Table* MixedColumn::get_subtable_ptr(size_t subtable_ndx) const -{ - return const_cast(this)->get_subtable_ptr(subtable_ndx); -} - -inline void MixedColumn::discard_child_accessors() noexcept -{ - m_data->discard_child_accessors(); -} - - -// -// Getters -// - -#define REALM_BIT63 0x8000000000000000ULL - -inline int64_t MixedColumn::get_value(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - - // Shift the unsigned value right - ensuring 0 gets in from left. - // Shifting signed integers right doesn't ensure 0's. - uint64_t value = uint64_t(m_data->get(ndx)) >> 1; - return int64_t(value); -} - -inline int64_t MixedColumn::get_int(size_t ndx) const noexcept -{ - // Get first 63 bits of the integer value - int64_t value = get_value(ndx); - - // restore 'sign'-bit from the column-type - MixedColType col_type = MixedColType(m_types->get(ndx)); - if (col_type == mixcol_IntNeg) { - // FIXME: Bad cast of result of '|' from unsigned to signed - value |= REALM_BIT63; // set sign bit (63) - } - else { - REALM_ASSERT_3(col_type, ==, mixcol_Int); - } - return value; -} - -inline bool MixedColumn::get_bool(size_t ndx) const noexcept -{ - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Bool); - - return (get_value(ndx) != 0); -} - -inline OldDateTime MixedColumn::get_olddatetime(size_t ndx) const noexcept -{ - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_OldDateTime); - - return OldDateTime(get_value(ndx)); -} - -inline float MixedColumn::get_float(size_t ndx) const noexcept -{ - static_assert(std::numeric_limits::is_iec559, "'float' is not IEEE"); - static_assert((sizeof(float) * CHAR_BIT == 32), "Assume 32 bit float."); - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Float); - - return type_punning(get_value(ndx)); -} - -inline double MixedColumn::get_double(size_t ndx) const noexcept -{ - static_assert(std::numeric_limits::is_iec559, "'double' is not IEEE"); - static_assert((sizeof(double) * CHAR_BIT == 64), "Assume 64 bit double."); - - int64_t int_val = get_value(ndx); - - // restore 'sign'-bit from the column-type - MixedColType col_type = MixedColType(m_types->get(ndx)); - if (col_type == mixcol_DoubleNeg) - int_val |= REALM_BIT63; // set sign bit (63) - else { - REALM_ASSERT_3(col_type, ==, mixcol_Double); - } - return type_punning(int_val); -} - -inline StringData MixedColumn::get_string(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_String); - REALM_ASSERT(m_binary_data); - - size_t data_ndx = size_t(int64_t(m_data->get(ndx)) >> 1); - return m_binary_data->get_string(data_ndx); -} - -inline BinaryData MixedColumn::get_binary(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Binary); - REALM_ASSERT(m_binary_data); - - size_t data_ndx = size_t(uint64_t(m_data->get(ndx)) >> 1); - return m_binary_data->get(data_ndx); -} - -inline Timestamp MixedColumn::get_timestamp(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Timestamp); - REALM_ASSERT(m_timestamp_data); - size_t data_ndx = size_t(uint64_t(m_data->get(ndx)) >> 1); - return m_timestamp_data->get(data_ndx); -} - -// -// Setters -// - -// Set a int64 value. -// Store 63 bit of the value in m_data. Store sign bit in m_types. - -inline void MixedColumn::set_int64(size_t ndx, int64_t value, MixedColType pos_type, MixedColType neg_type) -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - - // If sign-bit is set in value, 'store' it in the column-type - MixedColType coltype = ((value & REALM_BIT63) == 0) ? pos_type : neg_type; - - // Remove refs or binary data (sets type to double) - clear_value_and_discard_subtab_acc(ndx, coltype); // Throws - - // Shift value one bit and set lowest bit to indicate that this is not a ref - value = (value << 1) + 1; - m_data->set(ndx, value); -} - -inline void MixedColumn::set_int(size_t ndx, int64_t value) -{ - set_int64(ndx, value, mixcol_Int, mixcol_IntNeg); // Throws -} - -inline void MixedColumn::set_double(size_t ndx, double value) -{ - int64_t val64 = type_punning(value); - set_int64(ndx, val64, mixcol_Double, mixcol_DoubleNeg); // Throws -} - -inline void MixedColumn::set_value(size_t ndx, int64_t value, MixedColType coltype) -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - - // Remove refs or binary data (sets type to float) - clear_value_and_discard_subtab_acc(ndx, coltype); // Throws - - // Shift value one bit and set lowest bit to indicate that this is not a ref - int64_t v = (value << 1) + 1; - m_data->set(ndx, v); // Throws -} - -inline void MixedColumn::set_float(size_t ndx, float value) -{ - int64_t val64 = type_punning(value); - set_value(ndx, val64, mixcol_Float); // Throws -} - -inline void MixedColumn::set_bool(size_t ndx, bool value) -{ - set_value(ndx, (value ? 1 : 0), mixcol_Bool); // Throws -} - -inline void MixedColumn::set_olddatetime(size_t ndx, OldDateTime value) -{ - set_value(ndx, int64_t(value.get_olddatetime()), mixcol_OldDateTime); // Throws -} - -inline void MixedColumn::set_subtable(size_t ndx, const Table* t) -{ - REALM_ASSERT_3(ndx, <, m_types->size()); - typedef _impl::TableFriend tf; - ref_type ref; - if (t) { - ref = tf::clone(*t, get_alloc()); // Throws - } - else { - ref = tf::create_empty_table(get_alloc()); // Throws - } - // Remove any previous refs or binary data - clear_value_and_discard_subtab_acc(ndx, mixcol_Table); // Throws - m_data->set(ndx, ref); // Throws -} - -// -// Inserts -// - -inline void MixedColumn::insert_value(size_t row_ndx, int_fast64_t types_value, int_fast64_t data_value) -{ - size_t types_size = m_types->size(); // Slow - bool is_append = row_ndx == types_size; - size_t row_ndx_2 = is_append ? realm::npos : row_ndx; - size_t num_rows = 1; - m_types->insert_without_updating_index(row_ndx_2, types_value, num_rows); // Throws - m_data->do_insert(row_ndx_2, data_value, num_rows); // Throws -} - -// Insert a int64 value. -// Store 63 bit of the value in m_data. Store sign bit in m_types. - -inline void MixedColumn::insert_int(size_t ndx, int_fast64_t value, MixedColType type) -{ - int_fast64_t types_value = type; - // Shift value one bit and set lowest bit to indicate that this is not a ref - int_fast64_t data_value = 1 + (value << 1); - insert_value(ndx, types_value, data_value); // Throws -} - -inline void MixedColumn::insert_pos_neg(size_t ndx, int_fast64_t value, MixedColType pos_type, MixedColType neg_type) -{ - // 'store' the sign-bit in the integer-type - MixedColType type = (value & REALM_BIT63) == 0 ? pos_type : neg_type; - int_fast64_t types_value = type; - // Shift value one bit and set lowest bit to indicate that this is not a ref - int_fast64_t data_value = 1 + (value << 1); - insert_value(ndx, types_value, data_value); // Throws -} - -inline void MixedColumn::insert_int(size_t ndx, int_fast64_t value) -{ - insert_pos_neg(ndx, value, mixcol_Int, mixcol_IntNeg); // Throws -} - -inline void MixedColumn::insert_double(size_t ndx, double value) -{ - int_fast64_t value_2 = type_punning(value); - insert_pos_neg(ndx, value_2, mixcol_Double, mixcol_DoubleNeg); // Throws -} - -inline void MixedColumn::insert_float(size_t ndx, float value) -{ - int_fast64_t value_2 = type_punning(value); - insert_int(ndx, value_2, mixcol_Float); // Throws -} - -inline void MixedColumn::insert_bool(size_t ndx, bool value) -{ - int_fast64_t value_2 = int_fast64_t(value); - insert_int(ndx, value_2, mixcol_Bool); // Throws -} - -inline void MixedColumn::insert_olddatetime(size_t ndx, OldDateTime value) -{ - int_fast64_t value_2 = int_fast64_t(value.get_olddatetime()); - insert_int(ndx, value_2, mixcol_OldDateTime); // Throws -} - -inline void MixedColumn::insert_timestamp(size_t ndx, Timestamp value) -{ - ensure_timestamp_column(); - size_t data_ndx = m_timestamp_data->size(); - m_timestamp_data->add(value); // Throws - insert_int(ndx, int_fast64_t(data_ndx), mixcol_Timestamp); -} - -inline void MixedColumn::insert_string(size_t ndx, StringData value) -{ - ensure_binary_data_column(); - size_t blob_ndx = m_binary_data->size(); - m_binary_data->add_string(value); // Throws - - int_fast64_t value_2 = int_fast64_t(blob_ndx); - insert_int(ndx, value_2, mixcol_String); // Throws -} - -inline void MixedColumn::insert_binary(size_t ndx, BinaryData value) -{ - ensure_binary_data_column(); - size_t blob_ndx = m_binary_data->size(); - m_binary_data->add(value); // Throws - - int_fast64_t value_2 = int_fast64_t(blob_ndx); - insert_int(ndx, value_2, mixcol_Binary); // Throws -} - -inline void MixedColumn::insert_subtable(size_t ndx, const Table* t) -{ - typedef _impl::TableFriend tf; - ref_type ref; - if (t) { - ref = tf::clone(*t, get_alloc()); // Throws - } - else { - ref = tf::create_empty_table(get_alloc()); // Throws - } - int_fast64_t types_value = mixcol_Table; - int_fast64_t data_value = int_fast64_t(ref); - insert_value(ndx, types_value, data_value); // Throws -} - -inline void MixedColumn::erase(size_t row_ndx) -{ - size_t num_rows_to_erase = 1; - size_t prior_num_rows = size(); // Note that size() is slow - do_erase(row_ndx, num_rows_to_erase, prior_num_rows); // Throws -} - -inline void MixedColumn::move_last_over(size_t row_ndx) -{ - size_t prior_num_rows = size(); // Note that size() is slow - do_move_last_over(row_ndx, prior_num_rows); // Throws -} - -inline void MixedColumn::swap_rows(size_t row_ndx_1, size_t row_ndx_2) -{ - do_swap_rows(row_ndx_1, row_ndx_2); -} - -inline void MixedColumn::clear() -{ - size_t num_rows = size(); // Note that size() is slow - do_clear(num_rows); // Throws -} - -inline size_t MixedColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept -{ - const char* root_header = alloc.translate(root_ref); - ref_type types_ref = to_ref(Array::get(root_header, 0)); - return IntegerColumn::get_size_from_ref(types_ref, alloc); -} - -inline void MixedColumn::clear_value_and_discard_subtab_acc(size_t row_ndx, MixedColType new_type) -{ - MixedColType old_type = clear_value(row_ndx, new_type); - if (old_type == mixcol_Table) - m_data->discard_subtable_accessor(row_ndx); -} - -// Implementing pure virtual method of ColumnBase. -inline void MixedColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - REALM_ASSERT(!insert_nulls); - - size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx); - - int_fast64_t type_value = mixcol_Int; - m_types->insert_without_updating_index(row_ndx_2, type_value, num_rows_to_insert); // Throws - - // The least significant bit indicates that the rest of the bits form an - // integer value, so 1 is actually zero. - int_fast64_t data_value = 1; - m_data->do_insert(row_ndx_2, data_value, num_rows_to_insert); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void MixedColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool) -{ - do_erase(row_ndx, num_rows_to_erase, prior_num_rows); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void MixedColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool) -{ - do_move_last_over(row_ndx, prior_num_rows); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void MixedColumn::clear(size_t num_rows, bool) -{ - do_clear(num_rows); // Throws -} - -inline void MixedColumn::mark(int type) noexcept -{ - m_data->mark(type); -} - -inline void MixedColumn::refresh_accessor_tree(size_t col_ndx, const Spec& spec) -{ - ColumnBaseSimple::refresh_accessor_tree(col_ndx, spec); - - get_root_array()->init_from_parent(); - m_types->refresh_accessor_tree(col_ndx, spec); // Throws - m_data->refresh_accessor_tree(col_ndx, spec); // Throws - if (m_binary_data) { - REALM_ASSERT_3(get_root_array()->size(), >=, 3); - m_binary_data->refresh_accessor_tree(col_ndx, spec); // Throws - } - if (m_timestamp_data) { - REALM_ASSERT_3(get_root_array()->size(), >=, 4); - m_timestamp_data->refresh_accessor_tree(col_ndx, spec); // Throws - } - - - // See if m_binary_data needs to be created. - if (get_root_array()->size() >= 3) { - ref_type ref = get_root_array()->get_as_ref(2); - m_binary_data.reset(new BinaryColumn(get_alloc(), ref)); // Throws - m_binary_data->set_parent(get_root_array(), 2); - } - - // See if m_timestamp_data needs to be created. - if (get_root_array()->size() >= 4) { - ref_type ref = get_root_array()->get_as_ref(3); - // When adding/creating a Mixed column the user cannot specify nullability, so the "true" below - // makes it implicitly nullable, which may not be wanted. But it's OK since Mixed columns are not - // publicly supported - m_timestamp_data.reset(new TimestampColumn(true /*fixme*/, get_alloc(), ref)); // Throws - m_timestamp_data->set_parent(get_root_array(), 3); - } -} - -inline void MixedColumn::RefsColumn::refresh_accessor_tree(size_t col_ndx, const Spec& spec) -{ - SubtableColumnBase::refresh_accessor_tree(col_ndx, spec); // Throws - size_t spec_ndx_in_parent = 0; // Ignored because these are root tables - m_subtable_map.refresh_accessor_tree(spec_ndx_in_parent); // Throws -} - -} // namespace realm diff --git a/Example/Pods/Realm/include/core/realm/column_string.hpp b/Example/Pods/Realm/include/core/realm/column_string.hpp deleted file mode 100644 index 50bab6f..0000000 --- a/Example/Pods/Realm/include/core/realm/column_string.hpp +++ /dev/null @@ -1,378 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_STRING_HPP -#define REALM_COLUMN_STRING_HPP - -#include -#include -#include -#include -#include -#include - -namespace realm { - -// Pre-declarations -class StringIndex; - - -/// A string column (StringColumn) is a single B+-tree, and -/// the root of the column is the root of the B+-tree. Leaf nodes are -/// either of type ArrayString (array of small strings), -/// ArrayStringLong (array of medium strings), or ArrayBigBlobs (array -/// of big strings). -/// -/// A string column can optionally be equipped with a search index. If -/// it is, then the root ref of the index is stored in -/// Table::m_columns immediately after the root ref of the string -/// column. -class StringColumn : public ColumnBaseSimple { -public: - typedef StringData value_type; - - StringColumn(Allocator&, ref_type, bool nullable = false, size_t column_ndx = npos); - ~StringColumn() noexcept override; - - void destroy() noexcept override; - - size_t size() const noexcept final; - bool is_empty() const noexcept - { - return size() == 0; - } - - bool is_null(size_t ndx) const noexcept final; - void set_null(size_t ndx) final; - StringData get(size_t ndx) const noexcept; - void set(size_t ndx, StringData); - void add(); - void add(StringData value); - void insert(size_t ndx); - void insert(size_t ndx, StringData value); - void erase(size_t row_ndx); - void move_last_over(size_t row_ndx); - void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override; - void clear(); - - size_t count(StringData value) const; - size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const; - void find_all(IntegerColumn& result, StringData value, size_t begin = 0, size_t end = npos) const; - FindRes find_all_no_copy(StringData value, InternalFindResult& result) const; - - int compare_values(size_t, size_t) const noexcept override; - - //@{ - /// Find the lower/upper bound for the specified value assuming - /// that the elements are already sorted in ascending order - /// according to StringData::operator<(). - size_t lower_bound_string(StringData value) const noexcept; - size_t upper_bound_string(StringData value) const noexcept; - //@} - - void set_string(size_t, StringData) override; - - bool is_nullable() const noexcept final; - - // Search index - StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept final; - bool has_search_index() const noexcept override; - void set_search_index_ref(ref_type, ArrayParent*, size_t, bool) override; - void set_search_index_allow_duplicate_values(bool) noexcept override; - StringIndex* get_search_index() noexcept override; - const StringIndex* get_search_index() const noexcept override; - std::unique_ptr release_search_index() noexcept; - bool supports_search_index() const noexcept final - { - return true; - } - StringIndex* create_search_index() override; - - // Simply inserts all column values in the index in a loop - void populate_search_index(); - void destroy_search_index() noexcept override; - - // Optimizing data layout. enforce == true will enforce enumeration; - // enforce == false will auto-evaluate if it should be enumerated or not - bool auto_enumerate(ref_type& keys, ref_type& values, bool enforce = false) const; - - /// Compare two string columns for equality. - bool compare_string(const StringColumn&) const; - - enum LeafType { - leaf_type_Small, ///< ArrayString - leaf_type_Medium, ///< ArrayStringLong - leaf_type_Big ///< ArrayBigBlobs - }; - - std::unique_ptr get_leaf(size_t ndx, size_t& out_ndx_in_parent, LeafType& out_leaf_type) const; - - static ref_type create(Allocator&, size_t size = 0); - - static size_t get_size_from_ref(ref_type root_ref, Allocator&) noexcept; - - // Overrriding method in ColumnBase - ref_type write(size_t, size_t, size_t, _impl::OutputStream&) const override; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void clear(size_t, bool) override; - void set_ndx_in_parent(size_t ndx_in_parent) noexcept override; - void update_from_parent(size_t old_baseline) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - - void verify() const override; - void verify(const Table&, size_t) const override; - void to_dot(std::ostream&, StringData title) const override; - void do_dump_node_structure(std::ostream&, int) const override; - -private: - std::unique_ptr m_search_index; - bool m_nullable; - - LeafType get_block(size_t ndx, ArrayParent**, size_t& off, bool use_retval = false) const; - - /// If you are appending and have the size of the column readily available, - /// call the 4 argument version instead. If you are not appending, either - /// one is fine. - /// - /// \param row_ndx Must be `realm::npos` if appending. - void do_insert(size_t row_ndx, StringData value, size_t num_rows); - - /// If you are appending and you do not have the size of the column readily - /// available, call the 3 argument version instead. If you are not - /// appending, either one is fine. - /// - /// \param is_append Must be true if, and only if `row_ndx` is equal to the - /// size of the column (before insertion). - void do_insert(size_t row_ndx, StringData value, size_t num_rows, bool is_append); - - /// \param row_ndx Must be `realm::npos` if appending. - void bptree_insert(size_t row_ndx, StringData value, size_t num_rows); - - // Called by Array::bptree_insert(). - static ref_type leaf_insert(MemRef leaf_mem, ArrayParent&, size_t ndx_in_parent, Allocator&, size_t insert_ndx, - BpTreeNode::TreeInsert& state); - - class EraseLeafElem; - class CreateHandler; - class SliceHandler; - - void do_erase(size_t row_ndx, bool is_last); - void do_move_last_over(size_t row_ndx, size_t last_row_ndx); - void do_swap_rows(size_t row_ndx_1, size_t row_ndx_2); - void do_clear(); - - /// Root must be a leaf. Upgrades the root leaf as - /// necessary. Returns the type of the root leaf as it is upon - /// return. - LeafType upgrade_root_leaf(size_t value_size); - - void refresh_root_accessor(); - - void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; - - friend class BpTreeNode; - friend class ColumnBase; -}; - - -// Implementation: - -inline size_t StringColumn::size() const noexcept -{ - if (root_is_leaf()) { - bool long_strings = m_array->has_refs(); - if (!long_strings) { - // Small strings root leaf - ArrayString* leaf = static_cast(m_array.get()); - return leaf->size(); - } - bool is_big = m_array->get_context_flag(); - if (!is_big) { - // Medium strings root leaf - ArrayStringLong* leaf = static_cast(m_array.get()); - return leaf->size(); - } - // Big strings root leaf - ArrayBigBlobs* leaf = static_cast(m_array.get()); - return leaf->size(); - } - // Non-leaf root - BpTreeNode* node = static_cast(m_array.get()); - return node->get_bptree_size(); -} - -inline void StringColumn::add(StringData value) -{ - REALM_ASSERT(!(value.is_null() && !m_nullable)); - size_t row_ndx = realm::npos; - size_t num_rows = 1; - do_insert(row_ndx, value, num_rows); // Throws -} - -inline void StringColumn::add() -{ - add(m_nullable ? realm::null() : StringData("")); -} - -inline void StringColumn::insert(size_t row_ndx, StringData value) -{ - REALM_ASSERT(!(value.is_null() && !m_nullable)); - size_t column_size = this->size(); - REALM_ASSERT_3(row_ndx, <=, column_size); - size_t num_rows = 1; - bool is_append = row_ndx == column_size; - do_insert(row_ndx, value, num_rows, is_append); // Throws -} - -inline void StringColumn::insert(size_t row_ndx) -{ - insert(row_ndx, m_nullable ? realm::null() : StringData("")); -} - -inline void StringColumn::erase(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - bool is_last = row_ndx == last_row_ndx; - do_erase(row_ndx, is_last); // Throws -} - -inline void StringColumn::move_last_over(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -inline void StringColumn::swap_rows(size_t row_ndx_1, size_t row_ndx_2) -{ - do_swap_rows(row_ndx_1, row_ndx_2); // Throws -} - -inline void StringColumn::clear() -{ - do_clear(); // Throws -} - -inline int StringColumn::compare_values(size_t row1, size_t row2) const noexcept -{ - StringData a = get(row1); - StringData b = get(row2); - - if (a.is_null() && !b.is_null()) - return 1; - else if (b.is_null() && !a.is_null()) - return -1; - else if (a.is_null() && b.is_null()) - return 0; - - if (a == b) - return 0; - return utf8_compare(a, b) ? 1 : -1; -} - -inline void StringColumn::set_string(size_t row_ndx, StringData value) -{ - REALM_ASSERT(!(value.is_null() && !m_nullable)); - set(row_ndx, value); // Throws -} - -inline bool StringColumn::has_search_index() const noexcept -{ - return m_search_index != 0; -} - -inline StringIndex* StringColumn::get_search_index() noexcept -{ - return m_search_index.get(); -} - -inline const StringIndex* StringColumn::get_search_index() const noexcept -{ - return m_search_index.get(); -} - -inline size_t StringColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept -{ - const char* root_header = alloc.translate(root_ref); - bool root_is_leaf = !Array::get_is_inner_bptree_node_from_header(root_header); - if (root_is_leaf) { - bool long_strings = Array::get_hasrefs_from_header(root_header); - if (!long_strings) { - // Small strings leaf - return ArrayString::get_size_from_header(root_header); - } - bool is_big = Array::get_context_flag_from_header(root_header); - if (!is_big) { - // Medium strings leaf - return ArrayStringLong::get_size_from_header(root_header, alloc); - } - // Big strings leaf - return ArrayBigBlobs::get_size_from_header(root_header); - } - - return BpTreeNode::get_bptree_size_from_header(root_header); -} - -// Implementing pure virtual method of ColumnBase. -inline void StringColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - REALM_ASSERT(!insert_nulls || m_nullable); - - StringData value = m_nullable ? realm::null() : StringData(""); - bool is_append = (row_ndx == prior_num_rows); - do_insert(row_ndx, value, num_rows_to_insert, is_append); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void StringColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(num_rows_to_erase <= prior_num_rows); - REALM_ASSERT(row_ndx <= prior_num_rows - num_rows_to_erase); - - bool is_last = (row_ndx + num_rows_to_erase == prior_num_rows); - for (size_t i = num_rows_to_erase; i > 0; --i) { - size_t row_ndx_2 = row_ndx + i - 1; - do_erase(row_ndx_2, is_last); // Throws - } -} - -// Implementing pure virtual method of ColumnBase. -inline void StringColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx < prior_num_rows); - - size_t last_row_ndx = prior_num_rows - 1; - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -// Implementing pure virtual method of ColumnBase. -inline void StringColumn::clear(size_t, bool) -{ - do_clear(); // Throws -} - -} // namespace realm - -#endif // REALM_COLUMN_STRING_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_string_enum.hpp b/Example/Pods/Realm/include/core/realm/column_string_enum.hpp deleted file mode 100644 index be27ba0..0000000 --- a/Example/Pods/Realm/include/core/realm/column_string_enum.hpp +++ /dev/null @@ -1,311 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_STRING_ENUM_HPP -#define REALM_COLUMN_STRING_ENUM_HPP - -#include - -namespace realm { - -// Pre-declarations -class StringIndex; - - -/// From the point of view of the application, an enumerated strings column -/// (StringEnumColumn) is like a string column (StringColumn), yet it manages -/// its strings in such a way that each unique string is stored only once. In -/// fact, an enumerated strings column is a combination of two subcolumns; a -/// regular string column (StringColumn) that stores the unique strings, and an -/// integer column that stores one unique string index for each entry in the -/// enumerated strings column. -/// -/// In terms of the underlying node structure, the subcolumn containing the -/// unique strings is not a true part of the enumerated strings column. Instead -/// it is a part of the spec structure that describes the table of which the -/// enumerated strings column is a part. This way, the unique strings can be -/// shared across enumerated strings columns of multiple subtables. This also -/// means that the root of an enumerated strings column coincides with the root -/// of the integer subcolumn, and in some sense, an enumerated strings column is -/// just the integer subcolumn. -/// -/// An enumerated strings column can optionally be equipped with a -/// search index. If it is, then the root ref of the index is stored -/// in Table::m_columns immediately after the root ref of the -/// enumerated strings column. -class StringEnumColumn : public IntegerColumn { -public: - typedef StringData value_type; - - StringEnumColumn(Allocator&, ref_type ref, ref_type keys_ref, bool nullable, size_t column_ndx = npos); - ~StringEnumColumn() noexcept override; - void destroy() noexcept override; - MemRef clone_deep(Allocator& alloc) const override; - - int compare_values(size_t row1, size_t row2) const noexcept override - { - StringData a = get(row1); - StringData b = get(row2); - - if (a.is_null() && !b.is_null()) - return 1; - else if (b.is_null() && !a.is_null()) - return -1; - else if (a.is_null() && b.is_null()) - return 0; - - if (a == b) - return 0; - - return utf8_compare(a, b) ? 1 : -1; - } - - StringData get(size_t ndx) const noexcept; - bool is_null(size_t ndx) const noexcept final; - void set(size_t ndx, StringData value); - void set_null(size_t ndx) override; - void add(); - void add(StringData value); - void insert(size_t ndx); - void insert(size_t ndx, StringData value); - void erase(size_t row_ndx); - void move_last_over(size_t row_ndx); - void clear(); - bool is_nullable() const noexcept final; - - size_t count(StringData value) const; - size_t find_first(StringData value, size_t begin = 0, size_t end = npos) const; - void find_all(IntegerColumn& res, StringData value, size_t begin = 0, size_t end = npos) const; - FindRes find_all_no_copy(StringData value, InternalFindResult& result) const; - - size_t count(size_t key_index) const; - size_t find_first(size_t key_index, size_t begin = 0, size_t end = -1) const; - void find_all(IntegerColumn& res, size_t key_index, size_t begin = 0, size_t end = -1) const; - - //@{ - /// Find the lower/upper bound for the specified value assuming - /// that the elements are already sorted in ascending order - /// according to StringData::operator<(). - size_t lower_bound_string(StringData value) const noexcept; - size_t upper_bound_string(StringData value) const noexcept; - //@} - - void set_string(size_t, StringData) override; - - void adjust_keys_ndx_in_parent(int diff) noexcept; - - // Search index - StringData get_index_data(size_t ndx, StringIndex::StringConversionBuffer& buffer) const noexcept final; - void set_search_index_allow_duplicate_values(bool) noexcept override; - bool supports_search_index() const noexcept final - { - return true; - } - StringIndex* create_search_index() override; - void install_search_index(std::unique_ptr) noexcept; - void destroy_search_index() noexcept override; - - // Compare two string columns for equality - bool compare_string(const StringColumn&) const; - bool compare_string(const StringEnumColumn&) const; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void clear(size_t, bool) override; - void update_from_parent(size_t) noexcept override; - void refresh_accessor_tree(size_t, const Spec&) override; - - size_t get_key_ndx(StringData value) const; - size_t get_key_ndx_or_add(StringData value); - - StringColumn& get_keys(); - const StringColumn& get_keys() const; - -#ifdef REALM_DEBUG - void verify() const override; - void verify(const Table&, size_t) const override; - void do_dump_node_structure(std::ostream&, int) const override; - void to_dot(std::ostream&, StringData title) const override; -#endif - -private: - // Member variables - StringColumn m_keys; - bool m_nullable; - - /// If you are appending and have the size of the column readily available, - /// call the 4 argument version instead. If you are not appending, either - /// one is fine. - /// - /// \param row_ndx Must be `realm::npos` if appending. - void do_insert(size_t row_ndx, StringData value, size_t num_rows); - - /// If you are appending and you do not have the size of the column readily - /// available, call the 3 argument version instead. If you are not - /// appending, either one is fine. - /// - /// \param is_append Must be true if, and only if `row_ndx` is equal to the - /// size of the column (before insertion). - void do_insert(size_t row_ndx, StringData value, size_t num_rows, bool is_append); - - void do_erase(size_t row_ndx, bool is_last); - void do_move_last_over(size_t row_ndx, size_t last_row_ndx); - void do_clear(); -}; - - -// Implementation: - -inline StringData StringEnumColumn::get(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, IntegerColumn::size()); - size_t key_ndx = to_size_t(IntegerColumn::get(ndx)); - StringData sd = m_keys.get(key_ndx); - REALM_ASSERT_DEBUG(!(!m_nullable && sd.is_null())); - return sd; -} - -inline bool StringEnumColumn::is_null(size_t ndx) const noexcept -{ - return is_nullable() && get(ndx).is_null(); -} - -inline void StringEnumColumn::add() -{ - add(m_nullable ? realm::null() : StringData("")); -} - -inline void StringEnumColumn::add(StringData value) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - size_t row_ndx = realm::npos; - size_t num_rows = 1; - do_insert(row_ndx, value, num_rows); // Throws -} - -inline void StringEnumColumn::insert(size_t row_ndx) -{ - insert(row_ndx, m_nullable ? realm::null() : StringData("")); -} - -inline void StringEnumColumn::insert(size_t row_ndx, StringData value) -{ - REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); - size_t column_size = this->size(); - REALM_ASSERT_3(row_ndx, <=, column_size); - size_t num_rows = 1; - bool is_append = row_ndx == column_size; - do_insert(row_ndx, value, num_rows, is_append); // Throws -} - -inline void StringEnumColumn::erase(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - bool is_last = row_ndx == last_row_ndx; - do_erase(row_ndx, is_last); // Throws -} - -inline void StringEnumColumn::move_last_over(size_t row_ndx) -{ - size_t last_row_ndx = size() - 1; // Note that size() is slow - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -inline void StringEnumColumn::clear() -{ - do_clear(); // Throws -} - -// Overriding virtual method of Column. -inline void StringEnumColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - REALM_ASSERT(!insert_nulls || m_nullable); - - StringData value = m_nullable ? realm::null() : StringData(""); - bool is_append = (row_ndx == prior_num_rows); - do_insert(row_ndx, value, num_rows_to_insert, is_append); // Throws -} - -// Overriding virtual method of Column. -inline void StringEnumColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(num_rows_to_erase <= prior_num_rows); - REALM_ASSERT(row_ndx <= prior_num_rows - num_rows_to_erase); - - bool is_last = (row_ndx + num_rows_to_erase == prior_num_rows); - for (size_t i = num_rows_to_erase; i > 0; --i) { - size_t row_ndx_2 = row_ndx + i - 1; - do_erase(row_ndx_2, is_last); // Throws - } -} - -// Overriding virtual method of Column. -inline void StringEnumColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx < prior_num_rows); - - size_t last_row_ndx = prior_num_rows - 1; - do_move_last_over(row_ndx, last_row_ndx); // Throws -} - -// Overriding virtual method of Column. -inline void StringEnumColumn::clear(size_t, bool) -{ - do_clear(); // Throws -} - -inline size_t StringEnumColumn::lower_bound_string(StringData value) const noexcept -{ - return ColumnBase::lower_bound(*this, value); -} - -inline size_t StringEnumColumn::upper_bound_string(StringData value) const noexcept -{ - return ColumnBase::upper_bound(*this, value); -} - -inline void StringEnumColumn::set_string(size_t row_ndx, StringData value) -{ - set(row_ndx, value); // Throws -} - -inline void StringEnumColumn::set_null(size_t row_ndx) -{ - set(row_ndx, realm::null{}); -} - -inline StringColumn& StringEnumColumn::get_keys() -{ - return m_keys; -} - -inline const StringColumn& StringEnumColumn::get_keys() const -{ - return m_keys; -} - - -} // namespace realm - -#endif // REALM_COLUMN_STRING_ENUM_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_table.hpp b/Example/Pods/Realm/include/core/realm/column_table.hpp deleted file mode 100644 index ca5e38b..0000000 --- a/Example/Pods/Realm/include/core/realm/column_table.hpp +++ /dev/null @@ -1,601 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_TABLE_HPP -#define REALM_COLUMN_TABLE_HPP - -#include - -#include -#include -#include -#include - -namespace realm { - - -/// Base class for any type of column that can contain subtables. -// FIXME: Don't derive from IntegerColumn, but define a BpTree specialization. -class SubtableColumnBase : public IntegerColumn, public Table::Parent { -public: - void discard_child_accessors() noexcept; - - ~SubtableColumnBase() noexcept override; - - static ref_type create(Allocator&, size_t size = 0); - - Table* get_subtable_accessor(size_t) const noexcept override; - - void insert_rows(size_t, size_t, size_t, bool) override; - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - void clear(size_t, bool) override; - void swap_rows(size_t, size_t) override; - void discard_subtable_accessor(size_t) noexcept override; - void update_from_parent(size_t) noexcept override; - void adj_acc_insert_rows(size_t, size_t) noexcept override; - void adj_acc_erase_row(size_t) noexcept override; - void adj_acc_move_over(size_t, size_t) noexcept override; - void adj_acc_clear_root_table() noexcept override; - void adj_acc_swap_rows(size_t, size_t) noexcept override; - void mark(int) noexcept override; - bool supports_search_index() const noexcept override - { - return false; - } - StringIndex* create_search_index() override - { - return nullptr; - } - - void verify() const override; - void verify(const Table&, size_t) const override; - -protected: - /// A pointer to the table that this column is part of. For a free-standing - /// column, this pointer is null. - Table* const m_table; - - struct SubtableMap { - ~SubtableMap() noexcept - { - } - bool empty() const noexcept - { - return m_entries.empty(); - } - Table* find(size_t subtable_ndx) const noexcept; - void add(size_t subtable_ndx, Table*); - // Returns true if, and only if at least one entry was detached and - // removed from the map. - bool detach_and_remove_all() noexcept; - // Returns true if, and only if the entry was found and removed, and it - // was the last entry in the map. - bool detach_and_remove(size_t subtable_ndx) noexcept; - // Returns true if, and only if the entry was found and removed, and it - // was the last entry in the map. - bool remove(Table*) noexcept; - void update_from_parent(size_t old_baseline) const noexcept; - template - void adj_insert_rows(size_t row_ndx, size_t num_rows_inserted) noexcept; - // Returns true if, and only if an entry was found and removed, and it - // was the last entry in the map. - template - bool adj_erase_rows(size_t row_ndx, size_t num_rows_erased) noexcept; - // Returns true if, and only if an entry was found and removed, and it - // was the last entry in the map. - template - bool adj_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; - template - void adj_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - - void update_accessors(const size_t* col_path_begin, const size_t* col_path_end, - _impl::TableFriend::AccessorUpdater&); - void recursive_mark() noexcept; - void refresh_accessor_tree(size_t spec_ndx_in_parent); - - private: - struct SubtableEntry { - size_t m_subtable_ndx; - Table* m_table; - }; - typedef std::vector entries; - entries m_entries; - }; - - /// Contains all existing accessors that are attached to a subtable in this - /// column. It can map a row index into a pointer to the corresponding - /// accessor when it exists. - /// - /// There is an invariant in force: Either `m_table` is null, or there is an - /// additional referece count on `*m_table` when, and only when the map is - /// non-empty. - mutable SubtableMap m_subtable_map; - - SubtableColumnBase(Allocator&, ref_type, Table*, size_t column_ndx); - - /// Get a pointer to the accessor of the specified subtable. The - /// accessor will be created if it does not already exist. - /// - /// The returned table pointer must **always** end up being - /// wrapped in some instantiation of BasicTableRef<>. - /// - /// NOTE: This method must be used only for subtables with - /// independent specs, i.e. for elements of a MixedColumn. - Table* get_subtable_ptr(size_t subtable_ndx); - - // Overriding method in ArrayParent - void update_child_ref(size_t, ref_type) override; - - // Overriding method in ArrayParent - ref_type get_child_ref(size_t) const noexcept override; - - // Overriding method in Table::Parent - Table* get_parent_table(size_t*) noexcept override; - - // Overriding method in Table::Parent - void child_accessor_destroyed(Table*) noexcept override; - - /// Assumes that the two tables have the same spec. - static bool compare_subtable_rows(const Table&, const Table&); - - /// Construct a copy of the columns array of the specified table - /// and return just the ref to that array. - /// - /// In the clone, no string column will be of the enumeration - /// type. - ref_type clone_table_columns(const Table*); - - size_t* record_subtable_path(size_t* begin, size_t* end) noexcept override; - - void update_table_accessors(const size_t* col_path_begin, const size_t* col_path_end, - _impl::TableFriend::AccessorUpdater&); - - /// \param row_ndx Must be `realm::npos` if appending. - /// \param value The value to place in any newly created rows. - /// \param num_rows The number of rows to insert. - void do_insert(size_t row_ndx, int_fast64_t value, size_t num_rows); - - std::pair get_to_dot_parent(size_t ndx_in_parent) const override; - - friend class Table; -}; - - -class SubtableColumn : public SubtableColumnBase { -public: - /// Create a subtable column accessor and attach it to a - /// preexisting underlying structure of arrays. - /// - /// \param alloc The allocator to provide new memory. - /// - /// \param ref The memory reference of the underlying subtable that - /// we are creating an accessor for. - /// - /// \param table If this column is used as part of a table you must - /// pass a pointer to that table. Otherwise you must pass null. - /// - /// \param column_ndx If this column is used as part of a table - /// you must pass the logical index of the column within that - /// table. Otherwise you should pass zero. - SubtableColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx); - - ~SubtableColumn() noexcept override - { - } - - size_t get_subtable_size(size_t ndx) const noexcept; - - /// Get a pointer to the accessor of the specified subtable. The - /// accessor will be created if it does not already exist. - /// - /// The returned table pointer must **always** end up being - /// wrapped in some instantiation of BasicTableRef<>. - Table* get_subtable_ptr(size_t subtable_ndx); - - const Table* get_subtable_ptr(size_t subtable_ndx) const; - - // When passing a table to add() or insert() it is assumed that - // the table spec is compatible with this column. The number of - // columns must be the same, and the corresponding columns must - // have the same data type (as returned by - // Table::get_column_type()). - - void add(const Table* value = nullptr); - void insert(size_t ndx, const Table* value = nullptr); - void set(size_t ndx, const Table*); - void clear_table(size_t ndx); - - using SubtableColumnBase::insert; - - void erase_rows(size_t, size_t, size_t, bool) override; - void move_last_row_over(size_t, size_t, bool) override; - - /// Compare two subtable columns for equality. - bool compare_table(const SubtableColumn&) const; - - void refresh_accessor_tree(size_t, const Spec&) override; - -#ifdef REALM_DEBUG - void verify(const Table&, size_t) const override; - void do_dump_node_structure(std::ostream&, int) const override; - void to_dot(std::ostream&, StringData title) const override; -#endif - -private: - mutable size_t m_subspec_ndx; // Unknown if equal to `npos` - - size_t get_subspec_ndx() const noexcept; - - void destroy_subtable(size_t ndx) noexcept; - - void do_discard_child_accessors() noexcept override; -}; - - -// Implementation - -// Overriding virtual method of Column. -inline void SubtableColumnBase::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool insert_nulls) -{ - REALM_ASSERT_DEBUG(prior_num_rows == size()); - REALM_ASSERT(row_ndx <= prior_num_rows); - REALM_ASSERT(!insert_nulls); - - size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx); - int_fast64_t value = 0; - do_insert(row_ndx_2, value, num_rows_to_insert); // Throws -} - -// Overriding virtual method of Column. -inline void SubtableColumnBase::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, - bool broken_reciprocal_backlinks) -{ - IntegerColumn::erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, broken_reciprocal_backlinks); // Throws - - const bool fix_ndx_in_parent = true; - bool last_entry_removed = m_subtable_map.adj_erase_rows(row_ndx, num_rows_to_erase); - typedef _impl::TableFriend tf; - if (last_entry_removed) - tf::unbind_ptr(*m_table); -} - -// Overriding virtual method of Column. -inline void SubtableColumnBase::move_last_row_over(size_t row_ndx, size_t prior_num_rows, - bool broken_reciprocal_backlinks) -{ - IntegerColumn::move_last_row_over(row_ndx, prior_num_rows, broken_reciprocal_backlinks); // Throws - - const bool fix_ndx_in_parent = true; - size_t last_row_ndx = prior_num_rows - 1; - bool last_entry_removed = m_subtable_map.adj_move_over(last_row_ndx, row_ndx); - typedef _impl::TableFriend tf; - if (last_entry_removed) - tf::unbind_ptr(*m_table); -} - -inline void SubtableColumnBase::clear(size_t, bool) -{ - discard_child_accessors(); - clear_without_updating_index(); // Throws - // FIXME: This one is needed because - // IntegerColumn::clear_without_updating_index() forgets about the - // leaf type. A better solution should probably be sought after. - get_root_array()->set_type(Array::type_HasRefs); -} - -inline void SubtableColumnBase::swap_rows(size_t row_ndx_1, size_t row_ndx_2) -{ - IntegerColumn::swap_rows(row_ndx_1, row_ndx_2); // Throws - - const bool fix_ndx_in_parent = true; - m_subtable_map.adj_swap_rows(row_ndx_1, row_ndx_2); -} - -inline void SubtableColumnBase::mark(int type) noexcept -{ - if (type & mark_Recursive) - m_subtable_map.recursive_mark(); -} - -inline void SubtableColumnBase::adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - const bool fix_ndx_in_parent = false; - m_subtable_map.adj_insert_rows(row_ndx, num_rows); -} - -inline void SubtableColumnBase::adj_acc_erase_row(size_t row_ndx) noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - const bool fix_ndx_in_parent = false; - size_t num_rows_erased = 1; - bool last_entry_removed = m_subtable_map.adj_erase_rows(row_ndx, num_rows_erased); - typedef _impl::TableFriend tf; - if (last_entry_removed) - tf::unbind_ptr(*m_table); -} - -inline void SubtableColumnBase::adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - const bool fix_ndx_in_parent = false; - bool last_entry_removed = m_subtable_map.adj_move_over(from_row_ndx, to_row_ndx); - typedef _impl::TableFriend tf; - if (last_entry_removed) - tf::unbind_ptr(*m_table); -} - -inline void SubtableColumnBase::adj_acc_clear_root_table() noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - IntegerColumn::adj_acc_clear_root_table(); - discard_child_accessors(); -} - -inline void SubtableColumnBase::adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept -{ - const bool fix_ndx_in_parent = false; - m_subtable_map.adj_swap_rows(row_ndx_1, row_ndx_2); -} - -inline Table* SubtableColumnBase::get_subtable_accessor(size_t row_ndx) const noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - Table* subtable = m_subtable_map.find(row_ndx); - return subtable; -} - -inline void SubtableColumnBase::discard_subtable_accessor(size_t row_ndx) noexcept -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - bool last_entry_removed = m_subtable_map.detach_and_remove(row_ndx); - typedef _impl::TableFriend tf; - if (last_entry_removed) - tf::unbind_ptr(*m_table); -} - -inline void SubtableColumnBase::SubtableMap::add(size_t subtable_ndx, Table* table) -{ - SubtableEntry e; - e.m_subtable_ndx = subtable_ndx; - e.m_table = table; - m_entries.push_back(e); -} - -template -void SubtableColumnBase::SubtableMap::adj_insert_rows(size_t row_ndx, size_t num_rows_inserted) noexcept -{ - for (auto& entry : m_entries) { - if (entry.m_subtable_ndx >= row_ndx) { - entry.m_subtable_ndx += num_rows_inserted; - typedef _impl::TableFriend tf; - if (fix_ndx_in_parent) - tf::set_ndx_in_parent(*(entry.m_table), entry.m_subtable_ndx); - } - } -} - -template -bool SubtableColumnBase::SubtableMap::adj_erase_rows(size_t row_ndx, size_t num_rows_erased) noexcept -{ - if (m_entries.empty()) - return false; - typedef _impl::TableFriend tf; - auto end = m_entries.end(); - auto i = m_entries.begin(); - do { - if (i->m_subtable_ndx >= row_ndx + num_rows_erased) { - i->m_subtable_ndx -= num_rows_erased; - if (fix_ndx_in_parent) - tf::set_ndx_in_parent(*(i->m_table), i->m_subtable_ndx); - } - else if (i->m_subtable_ndx >= row_ndx) { - // Must hold a counted reference while detaching - TableRef table(i->m_table); - tf::detach(*table); - // Move last over - *i = *--end; - continue; - } - ++i; - } while (i != end); - m_entries.erase(end, m_entries.end()); - return m_entries.empty(); -} - - -template -bool SubtableColumnBase::SubtableMap::adj_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept -{ - typedef _impl::TableFriend tf; - - size_t i = 0, n = m_entries.size(); - // We return true if, and only if we remove the last entry in the map. We - // need special handling for the case, where the set of entries are already - // empty, otherwise the final return statement would return true in this - // case, even though we didn't actually remove an entry. - if (n == 0) - return false; - - while (i < n) { - SubtableEntry& e = m_entries[i]; - if (REALM_UNLIKELY(e.m_subtable_ndx == to_row_ndx)) { - // Must hold a counted reference while detaching - TableRef table(e.m_table); - tf::detach(*table); - // Delete entry by moving last over (faster and avoids invalidating - // iterators) - e = m_entries[--n]; - m_entries.pop_back(); - } - else { - if (REALM_UNLIKELY(e.m_subtable_ndx == from_row_ndx)) { - e.m_subtable_ndx = to_row_ndx; - if (fix_ndx_in_parent) - tf::set_ndx_in_parent(*(e.m_table), e.m_subtable_ndx); - } - ++i; - } - } - return m_entries.empty(); -} - -template -void SubtableColumnBase::SubtableMap::adj_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept -{ - using tf = _impl::TableFriend; - for (auto& entry : m_entries) { - if (REALM_UNLIKELY(entry.m_subtable_ndx == row_ndx_1)) { - entry.m_subtable_ndx = row_ndx_2; - if (fix_ndx_in_parent) - tf::set_ndx_in_parent(*(entry.m_table), entry.m_subtable_ndx); - } - else if (REALM_UNLIKELY(entry.m_subtable_ndx == row_ndx_2)) { - entry.m_subtable_ndx = row_ndx_1; - if (fix_ndx_in_parent) - tf::set_ndx_in_parent(*(entry.m_table), entry.m_subtable_ndx); - } - } -} - -inline SubtableColumnBase::SubtableColumnBase(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx) - : IntegerColumn(alloc, ref, column_ndx) // Throws - , m_table(table) -{ -} - -inline void SubtableColumnBase::update_child_ref(size_t child_ndx, ref_type new_ref) -{ - set(child_ndx, new_ref); -} - -inline ref_type SubtableColumnBase::get_child_ref(size_t child_ndx) const noexcept -{ - return get_as_ref(child_ndx); -} - -inline void SubtableColumnBase::discard_child_accessors() noexcept -{ - bool last_entry_removed = m_subtable_map.detach_and_remove_all(); - if (last_entry_removed && m_table) - _impl::TableFriend::unbind_ptr(*m_table); -} - -inline SubtableColumnBase::~SubtableColumnBase() noexcept -{ - discard_child_accessors(); -} - -inline bool SubtableColumnBase::compare_subtable_rows(const Table& a, const Table& b) -{ - return _impl::TableFriend::compare_rows(a, b); -} - -inline ref_type SubtableColumnBase::clone_table_columns(const Table* t) -{ - return _impl::TableFriend::clone_columns(*t, get_root_array()->get_alloc()); -} - -inline ref_type SubtableColumnBase::create(Allocator& alloc, size_t size) -{ - return IntegerColumn::create(alloc, Array::type_HasRefs, size); // Throws -} - -inline size_t* SubtableColumnBase::record_subtable_path(size_t* begin, size_t* end) noexcept -{ - if (end == begin) - return 0; // Error, not enough space in buffer - *begin++ = get_column_index(); - if (end == begin) - return 0; // Error, not enough space in buffer - return _impl::TableFriend::record_subtable_path(*m_table, begin, end); -} - -inline void SubtableColumnBase::update_table_accessors(const size_t* col_path_begin, const size_t* col_path_end, - _impl::TableFriend::AccessorUpdater& updater) -{ - // This function must assume no more than minimal consistency of the - // accessor hierarchy. This means in particular that it cannot access the - // underlying node structure. See AccessorConsistencyLevels. - - m_subtable_map.update_accessors(col_path_begin, col_path_end, updater); // Throws -} - -inline void SubtableColumnBase::do_insert(size_t row_ndx, int_fast64_t value, size_t num_rows) -{ - IntegerColumn::insert_without_updating_index(row_ndx, value, num_rows); // Throws - bool is_append = row_ndx == realm::npos; - if (!is_append) { - const bool fix_ndx_in_parent = true; - m_subtable_map.adj_insert_rows(row_ndx, num_rows); - } -} - - -inline SubtableColumn::SubtableColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx) - : SubtableColumnBase(alloc, ref, table, column_ndx) - , m_subspec_ndx(realm::npos) -{ -} - -inline const Table* SubtableColumn::get_subtable_ptr(size_t subtable_ndx) const -{ - return const_cast(this)->get_subtable_ptr(subtable_ndx); -} - -inline void SubtableColumn::refresh_accessor_tree(size_t col_ndx, const Spec& spec) -{ - SubtableColumnBase::refresh_accessor_tree(col_ndx, spec); // Throws - m_subspec_ndx = spec.get_subspec_ndx(col_ndx); - m_subtable_map.refresh_accessor_tree(m_subspec_ndx); // Throws -} - -inline size_t SubtableColumn::get_subspec_ndx() const noexcept -{ - if (REALM_UNLIKELY(m_subspec_ndx == realm::npos)) { - typedef _impl::TableFriend tf; - const Spec& spec = tf::get_spec(*m_table); - m_subspec_ndx = spec.get_subspec_ndx(get_column_index()); - } - return m_subspec_ndx; -} - - -} // namespace realm - -#endif // REALM_COLUMN_TABLE_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_timestamp.hpp b/Example/Pods/Realm/include/core/realm/column_timestamp.hpp deleted file mode 100644 index 7e3ce07..0000000 --- a/Example/Pods/Realm/include/core/realm/column_timestamp.hpp +++ /dev/null @@ -1,155 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_TIMESTAMP_HPP -#define REALM_COLUMN_TIMESTAMP_HPP - -#include -#include - -namespace realm { - -// Inherits from ColumnTemplate to get a compare_values() that can be called without knowing the -// column type -class TimestampColumn : public ColumnBaseSimple { -public: - TimestampColumn(bool nullable, Allocator& alloc, ref_type ref, size_t col_ndx = npos); - - static ref_type create(Allocator& alloc, size_t size, bool nullable); - static size_t get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept; - - /// Get the number of entries in this column. This operation is relatively - /// slow. - size_t size() const noexcept override; - /// Whether or not this column is nullable. - bool is_nullable() const noexcept override; - /// Whether or not the value at \a row_ndx is NULL. If the column is not - /// nullable, always returns false. - bool is_null(size_t row_ndx) const noexcept override; - /// Sets the value at \a row_ndx to be NULL. - /// \throw LogicError Thrown if this column is not nullable. - void set_null(size_t row_ndx) override; - void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) override; - void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, - bool broken_reciprocal_backlinks) override; - void move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool broken_reciprocal_backlinks) override; - void clear(size_t num_rows, bool broken_reciprocal_backlinks) override; - void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override; - void destroy() noexcept override; - - bool has_search_index() const noexcept final - { - return bool(m_search_index); - } - StringIndex* get_search_index() noexcept final - { - return m_search_index.get(); - } - StringIndex* get_search_index() const noexcept final - { - return m_search_index.get(); - } - void destroy_search_index() noexcept override; - void set_search_index_ref(ref_type ref, ArrayParent* parent, size_t ndx_in_parent, - bool allow_duplicate_values) final; - void populate_search_index(); - StringIndex* create_search_index() override; - bool supports_search_index() const noexcept final - { - return true; - } - - StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept override; - ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const override; - void update_from_parent(size_t old_baseline) noexcept override; - void set_ndx_in_parent(size_t ndx) noexcept override; - void refresh_accessor_tree(size_t new_col_ndx, const Spec&) override; - - void verify() const override; - void to_dot(std::ostream&, StringData title = StringData()) const override; - void do_dump_node_structure(std::ostream&, int level) const override; - void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; - - void add(const Timestamp& ts = Timestamp{}); - Timestamp get(size_t row_ndx) const noexcept; - void set(size_t row_ndx, const Timestamp& ts); - bool compare(const TimestampColumn& c) const noexcept; - int compare_values(size_t row1, size_t row2) const noexcept override; - - Timestamp maximum(size_t* result_index) const; - Timestamp minimum(size_t* result_index) const; - size_t count(Timestamp) const; - void erase(size_t row_ndx, bool is_last); - - template - size_t find(Timestamp value, size_t begin, size_t end) const noexcept - { - // FIXME: Here we can do all sorts of clever optimizations. Use bithack-search on seconds, then for each match - // check nanoseconds, etc. Lots of possibilities. Below code is naive and slow but works. - - Condition cond; - for (size_t t = begin; t < end; t++) { - Timestamp ts = get(t); - if (cond(ts, value, ts.is_null(), value.is_null())) - return t; - } - return npos; - } - - typedef Timestamp value_type; - -private: - std::unique_ptr>> m_seconds; - std::unique_ptr> m_nanoseconds; - - std::unique_ptr m_search_index; - bool m_nullable; - - template - class CreateHandler; - - template - Timestamp minmax(size_t* result_index) const noexcept - { - // Condition is realm::Greater for maximum and realm::Less for minimum. - - if (size() == 0) { - if (result_index) - *result_index = npos; - return Timestamp{}; - } - - Timestamp best = get(0); - size_t best_index = 0; - - for (size_t i = 1; i < size(); ++i) { - Timestamp candidate = get(i); - if (Condition()(candidate, best, candidate.is_null(), best.is_null())) { - best = candidate; - best_index = i; - } - } - if (result_index) - *result_index = best_index; - return best; - } -}; - -} // namespace realm - -#endif // REALM_COLUMN_TIMESTAMP_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_tpl.hpp b/Example/Pods/Realm/include/core/realm/column_tpl.hpp deleted file mode 100644 index 2411007..0000000 --- a/Example/Pods/Realm/include/core/realm/column_tpl.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_TPL_HPP -#define REALM_COLUMN_TPL_HPP - -#include - -#include -#include -#include - -namespace realm { - -template -class FloatDoubleNode; -template -class IntegerNode; -template -class SequentialGetter; - -template -struct ColumnTypeTraits2; - -template -struct ColumnTypeTraits2 { - typedef IntegerColumn column_type; - typedef ArrayInteger array_type; -}; -template -struct ColumnTypeTraits2 { - typedef IntegerColumn column_type; - typedef ArrayInteger array_type; -}; -template -struct ColumnTypeTraits2 { - typedef FloatColumn column_type; - typedef ArrayFloat array_type; -}; -template -struct ColumnTypeTraits2 { - typedef DoubleColumn column_type; - typedef ArrayDouble array_type; -}; - - -namespace _impl { - -template -struct FindInLeaf { - using LeafType = typename ColType::LeafType; - - template - static bool find(const LeafType& leaf, T target, size_t local_start, size_t local_end, size_t leaf_start, - QueryState& state) - { - Condition cond; - bool cont = true; - // todo, make an additional loop with hard coded `false` instead of is_null(v) for non-nullable columns - bool null_target = null::is_null_float(target); - for (size_t local_index = local_start; cont && local_index < local_end; local_index++) { - auto v = leaf.get(local_index); - if (cond(v, target, null::is_null_float(v), null_target)) { - cont = state.template match(leaf_start + local_index, 0, static_cast(v)); - } - } - return cont; - } -}; - -template <> -struct FindInLeaf { - using LeafType = IntegerColumn::LeafType; - - template - static bool find(const LeafType& leaf, T target, size_t local_start, size_t local_end, size_t leaf_start, - QueryState& state) - { - const int c = Condition::condition; - return leaf.find(c, action, target, local_start, local_end, leaf_start, &state); - } -}; - -template <> -struct FindInLeaf { - using LeafType = IntNullColumn::LeafType; - - template - static bool find(const LeafType& leaf, T target, size_t local_start, size_t local_end, size_t leaf_start, - QueryState& state) - { - constexpr int cond = Condition::condition; - return leaf.find(cond, action, target, local_start, local_end, leaf_start, &state); - } -}; - -} // namespace _impl - -template -R aggregate(const ColType& column, T target, size_t start, size_t end, size_t limit, size_t* return_ndx) -{ - if (end == npos) - end = column.size(); - - QueryState state; - state.init(action, nullptr, limit); - SequentialGetter sg{&column}; - - bool cont = true; - for (size_t s = start; cont && s < end;) { - sg.cache_next(s); - size_t start2 = s - sg.m_leaf_start; - size_t end2 = sg.local_end(end); - cont = _impl::FindInLeaf::template find(*sg.m_leaf_ptr, target, start2, end2, - sg.m_leaf_start, state); - s = sg.m_leaf_start + end2; - } - - if (return_ndx) - *return_ndx = action == act_Sum ? state.m_match_count : state.m_minmax_index; - - return state.m_state; -} - - -} // namespace realm - -#endif // REALM_COLUMN_TPL_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_type.hpp b/Example/Pods/Realm/include/core/realm/column_type.hpp deleted file mode 100644 index 5a6e21c..0000000 --- a/Example/Pods/Realm/include/core/realm/column_type.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_TYPE_HPP -#define REALM_COLUMN_TYPE_HPP - -namespace realm { - - -// Note: Enumeration value assignments must be kept in sync with -// . -enum ColumnType { - // Column types - col_type_Int = 0, - col_type_Bool = 1, - col_type_String = 2, - col_type_StringEnum = 3, // double refs - col_type_Binary = 4, - col_type_Table = 5, - col_type_Mixed = 6, - col_type_OldDateTime = 7, - col_type_Timestamp = 8, - col_type_Float = 9, - col_type_Double = 10, - col_type_Reserved4 = 11, // Decimal - col_type_Link = 12, - col_type_LinkList = 13, - col_type_BackLink = 14 -}; - - -// Column attributes can be combined using bitwise or. -enum ColumnAttr { - col_attr_None = 0, - col_attr_Indexed = 1, - - /// Specifies that this column forms a unique constraint. It requires - /// `col_attr_Indexed`. - col_attr_Unique = 2, - - /// Reserved for future use. - col_attr_Reserved = 4, - - /// Specifies that the links of this column are strong, not weak. Applies - /// only to link columns (`type_Link` and `type_LinkList`). - col_attr_StrongLinks = 8, - - /// Specifies that elements in the column can be null. - col_attr_Nullable = 16 -}; - - -} // namespace realm - -#endif // REALM_COLUMN_TYPE_HPP diff --git a/Example/Pods/Realm/include/core/realm/column_type_traits.hpp b/Example/Pods/Realm/include/core/realm/column_type_traits.hpp deleted file mode 100644 index df9c236..0000000 --- a/Example/Pods/Realm/include/core/realm/column_type_traits.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_COLUMN_TYPE_TRAITS_HPP -#define REALM_COLUMN_TYPE_TRAITS_HPP - -#include -#include -#include - -namespace realm { - -class OldDateTime; -class ArrayBinary; -class ArrayInteger; -class ArrayIntNull; -template -class BasicArray; - -template -struct ColumnTypeTraits; - -template <> -struct ColumnTypeTraits { - using column_type = Column; - using leaf_type = ArrayInteger; - using sum_type = int64_t; - using minmax_type = int64_t; - static const DataType id = type_Int; - static const ColumnType column_id = col_type_Int; - static const ColumnType real_column_type = col_type_Int; -}; - -template <> -struct ColumnTypeTraits> { - using column_type = Column>; - using leaf_type = ArrayIntNull; - using sum_type = int64_t; - using minmax_type = int64_t; - static const DataType id = type_Int; - static const ColumnType column_id = col_type_Int; - static const ColumnType real_column_type = col_type_Int; -}; - -template <> -struct ColumnTypeTraits : ColumnTypeTraits { - static const DataType id = type_Bool; - static const ColumnType column_id = col_type_Bool; -}; - -template <> -struct ColumnTypeTraits> : ColumnTypeTraits> { - static const DataType id = type_Bool; - static const ColumnType column_id = col_type_Bool; -}; - -template <> -struct ColumnTypeTraits { - using column_type = FloatColumn; - using leaf_type = BasicArray; - using sum_type = double; - using minmax_type = float; - static const DataType id = type_Float; - static const ColumnType column_id = col_type_Float; - static const ColumnType real_column_type = col_type_Float; -}; - -template <> -struct ColumnTypeTraits { - using column_type = DoubleColumn; - using leaf_type = BasicArray; - using sum_type = double; - using minmax_type = double; - static const DataType id = type_Double; - static const ColumnType column_id = col_type_Double; - static const ColumnType real_column_type = col_type_Double; -}; - -template <> -struct ColumnTypeTraits : ColumnTypeTraits { - static const DataType id = type_OldDateTime; - static const ColumnType column_id = col_type_OldDateTime; -}; - -template <> -struct ColumnTypeTraits> : ColumnTypeTraits> { - static const DataType id = type_OldDateTime; - static const ColumnType column_id = col_type_OldDateTime; -}; - -template <> -struct ColumnTypeTraits { - using column_type = StringEnumColumn; - using leaf_type = ArrayInteger; - using sum_type = int64_t; - static const DataType id = type_String; - static const ColumnType column_id = col_type_String; - static const ColumnType real_column_type = col_type_String; -}; - -template <> -struct ColumnTypeTraits { - using column_type = BinaryColumn; - using leaf_type = ArrayBinary; - static const DataType id = type_Binary; - static const ColumnType column_id = col_type_Binary; - static const ColumnType real_column_type = col_type_Binary; -}; - -template -struct GetColumnType; -template <> -struct GetColumnType { - using type = IntegerColumn; -}; -template <> -struct GetColumnType { - using type = IntNullColumn; -}; -template -struct GetColumnType { - // FIXME: Null definition - using type = FloatColumn; -}; -template -struct GetColumnType { - // FIXME: Null definition - using type = DoubleColumn; -}; - -// Only purpose is to return 'double' if and only if source column (T) is float and you're doing a sum (A) -template -struct ColumnTypeTraitsSum { - typedef T sum_type; -}; - -template <> -struct ColumnTypeTraitsSum { - typedef double sum_type; -}; - -template -struct ColumnTypeTraitsSum, A> { - using sum_type = int64_t; -}; -} - -#endif // REALM_COLUMN_TYPE_TRAITS_HPP diff --git a/Example/Pods/Realm/include/core/realm/data_type.hpp b/Example/Pods/Realm/include/core/realm/data_type.hpp deleted file mode 100644 index 580982f..0000000 --- a/Example/Pods/Realm/include/core/realm/data_type.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_DATA_TYPE_HPP -#define REALM_DATA_TYPE_HPP - -namespace realm { - -// Note: Value assignments must be kept in sync with -// Note: Value assignments must be kept in sync with -// Note: Value assignments must be kept in sync with -// Note: Value assignments must be kept in sync with "com/realm/ColumnType.java" -// Note: Any change to this enum is a file-format breaking change. -enum DataType { - type_Int = 0, - type_Bool = 1, - type_Float = 9, - type_Double = 10, - type_String = 2, - type_Binary = 4, - type_OldDateTime = 7, - type_Timestamp = 8, - type_Table = 5, - type_Mixed = 6, - type_Link = 12, - type_LinkList = 13 -}; - -/// See Descriptor::set_link_type(). -enum LinkType { - link_Strong, - link_Weak, -}; - -} // namespace realm - -#endif // REALM_DATA_TYPE_HPP diff --git a/Example/Pods/Realm/include/core/realm/descriptor.hpp b/Example/Pods/Realm/include/core/realm/descriptor.hpp deleted file mode 100644 index 10433eb..0000000 --- a/Example/Pods/Realm/include/core/realm/descriptor.hpp +++ /dev/null @@ -1,820 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_DESCRIPTOR_HPP -#define REALM_DESCRIPTOR_HPP - -#include - -#include -#include -#include - - -namespace realm { - -namespace _impl { -class DescriptorFriend; -} - - -/// Accessor for table type descriptors. -/// -/// A table type descriptor is an entity that specifies the dynamic -/// type of a Realm table. Objects of this class are accessors -/// through which the descriptor can be inspected and -/// changed. Accessors can become detached, see is_attached() for more -/// on this. The descriptor itself is stored inside the database file, -/// or elsewhere in case of a free-standing table or a table in a -/// free-standing group. -/// -/// The dynamic type consists first, and foremost of an ordered list -/// of column descriptors. Each column descriptor specifies the name -/// and type of the column. -/// -/// When a table has a subtable column, every cell in than column -/// contains a subtable. All those subtables have the same dynamic -/// type, and therefore have a shared descriptor. See is_root() for -/// more on this. -/// -/// The Table class contains convenience methods, such as -/// Table::get_column_count() and Table::add_column(), that allow you -/// to inspect and change the dynamic type of simple tables without -/// resorting to use of descriptors. For example, the following two -/// statements have the same effect: -/// -/// table->add_column(type, name); -/// table->get_descriptor()->add_column(type, name); -/// -/// Note, however, that this equivalence holds only as long as no -/// shared subtable descriptors are involved. -/// -/// \sa Table::get_descriptor() -class Descriptor : public std::enable_shared_from_this { -public: - /// Get the number of columns in the associated tables. - size_t get_column_count() const noexcept; - - /// Get the type of the column at the specified index. - /// - /// The consequences of specifying a column index that is out of - /// range, are undefined. - DataType get_column_type(size_t column_ndx) const noexcept; - - /// Get the name of the column at the specified index. - /// - /// The consequences of specifying a column index that is out of - /// range, are undefined. - StringData get_column_name(size_t column_ndx) const noexcept; - - /// Search for a column with the specified name. - /// - /// This function finds the first column with the specified name, - /// and returns its index. If there are no such columns, it - /// returns `not_found`. - size_t get_column_index(StringData name) const noexcept; - - /// Get the index of the column to which links in the column at the - /// specified index refer. - /// - /// The consequences of specifying a column index that is out of - /// range, are undefined. - /// - /// The consequences of specifying a column index that does not refer - /// to a link column, are undefined. - size_t get_column_link_target(size_t column_ndx) const noexcept; - - /// Get whether or not the specified column is nullable. - /// - /// The consequences of specifying a column index that is out of - /// range, are undefined. - bool is_nullable(size_t column_ndx) const noexcept; - - /// \defgroup descriptor_column_accessors Accessing Columns Via A Descriptor - /// - /// add_column() and add_column_link() are a shorthands for calling - /// insert_column() and insert_column_link(), respectively, with a column - /// index equal to the original number of columns. The returned value is - /// that column index. - /// - /// insert_column() inserts a new column into all the tables associated with - /// this descriptor. If any of the tables are not empty, the new column will - /// be filled with the default value associated with the specified data - /// type. This function cannot be used to insert link-type columns. For - /// that, you have to use insert_column_link() instead. - /// - /// This function modifies the dynamic type of all the tables that - /// share this descriptor. It does this by inserting a new column - /// with the specified name and type into the descriptor at the - /// specified index, and into each of the tables that share this - /// descriptor. - /// - /// insert_column_link() is like insert_column(), but inserts a link-type - /// column to a group-level table. It is not possible to add link-type - /// columns to tables that are not group-level tables. This functions must - /// be used in place of insert_column() when the column type is `type_Link` - /// or `type_LinkList`. A link-type column is associated with a particular - /// target table. All links in a link-type column refer to rows in the - /// target table of that column. The target table must also be a group-level - /// table, and it must belong to the same group as the origin table. - /// - /// \param name Name of new column. All strings are valid column names as - /// long as they are valid UTF-8 encodings and the number of bytes does not - /// exceed `max_column_name_length`. An attempt to add a column with a name - /// that is longer than `max_column_name_length` will cause an exception to - /// be thrown. - /// - /// \param subdesc If a non-null pointer is passed, and the - /// specified type is `type_Table`, then this function - /// automatically retrieves the descriptor associated with the new - /// subtable column, and stores a reference to its accessor in - /// `*subdesc`. - /// - /// \param col_ndx Insert the new column at this index. Preexisting columns - /// at indexes equal to, or greater than `col_ndx` will be shifted to the - /// next higher index. It is an error to specify an index that is greater - /// than the number of columns prior to the insertion. - /// - /// \param link_type See set_link_type(). - /// - /// \sa Table::add_column() - /// \sa Table::insert_column() - /// \sa Table::add_column_link() - /// \sa Table::insert_column_link() - /// \sa is_root() - //@{ - - static const size_t max_column_name_length = 63; - - size_t add_column(DataType type, StringData name, DescriptorRef* subdesc = nullptr, bool nullable = false); - - void insert_column(size_t col_ndx, DataType type, StringData name, DescriptorRef* subdesc = nullptr, - bool nullable = false); - - size_t add_column_link(DataType type, StringData name, Table& target, LinkType = link_Weak); - void insert_column_link(size_t col_ndx, DataType type, StringData name, Table& target, LinkType = link_Weak); - //@} - - /// Remove the specified column from each of the associated - /// tables. If the removed column is the only column in the - /// descriptor, then the table size will drop to zero for all - /// tables that were not already empty. - /// - /// This function modifies the dynamic type of all the tables that - /// share this descriptor. It does this by removing the column at - /// the specified index from the descriptor, and from each of the - /// tables that share this descriptor. The consequences of - /// specifying a column index that is out of range, are undefined. - /// - /// If the removed column was a subtable column, then the - /// associated descriptor accessor will be detached, if it - /// exists. This function will also detach all accessors of - /// subtables of the root table. Only the accessor of the root - /// table will remain attached. The root table is the table - /// associated with the root descriptor. - /// - /// \param col_ndx The index of the column to be removed. It is an error to - /// specify an index that is greater than, or equal to the number of - /// columns. - /// - /// \sa is_root() - /// \sa Table::remove_column() - void remove_column(size_t col_ndx); - - /// Rename the specified column. - /// - /// This function modifies the dynamic type of all the tables that - /// share this descriptor. The consequences of specifying a column - /// index that is out of range, are undefined. - /// - /// This function will detach all accessors of subtables of the - /// root table. Only the accessor of the root table will remain - /// attached. The root table is the table associated with the root - /// descriptor. - /// - /// \param col_ndx The index of the column to be renamed. It is an error to - /// specify an index that is greater than, or equal to the number of - /// columns. - /// - /// \param new_name The new name of the column. - /// - /// \sa is_root() - /// \sa Table::rename_column() - void rename_column(size_t col_ndx, StringData new_name); - - /// There are two kinds of links, 'weak' and 'strong'. A strong link is one - /// that implies ownership, i.e., that the origin row (parent) owns the - /// target row (child). Simply stated, this means that when the origin row - /// (parent) is removed, so is the target row (child). If there are multiple - /// strong links to a target row, the origin rows share ownership, and the - /// target row is removed when the last owner disappears. Weak links do not - /// imply ownership, and will be nullified or removed when the target row - /// disappears. - /// - /// To put this in precise terms; when a strong link is broken, and the - /// target row has no other strong links to it, the target row is removed. A - /// row that is implicitly removed in this way, is said to be - /// *cascade-removed*. When a weak link is broken, nothing is - /// cascade-removed. - /// - /// A link is considered broken if - /// - /// - the link is nullified, removed, or replaced by a different link - /// (Row::nullify_link(), Row::set_link(), LinkView::remove_link(), - /// LinkView::set_link(), LinkView::clear()), or if - /// - /// - the origin row is explicitly removed (Row::move_last_over(), - /// Table::clear()), or if - /// - /// - the origin row is cascade-removed, or if - /// - /// - the origin column is removed from the table (Table::remove_column()), - /// or if - /// - /// - the origin table is removed from the group. - /// - /// Note that a link is *not* considered broken when it is replaced by a - /// link to the same target row. I.e., no no rows will be cascade-removed - /// due to such an operation. - /// - /// When a row is explicitly removed (such as by Table::move_last_over()), - /// all links to it are automatically removed or nullified. For single link - /// columns (type_Link), links to the removed row are nullified. For link - /// list columns (type_LinkList), links to the removed row are removed from - /// the list. - /// - /// When a row is cascade-removed there can no longer be any strong links to - /// it, but if there are any weak links, they will be removed or nullified. - /// - /// It is important to understand that this cascade-removal scheme is too - /// simplistic to enable detection and removal of orphaned link-cycles. In - /// this respect, it suffers from the same limitations as a reference - /// counting scheme generally does. - /// - /// It is also important to understand, that the possible presence of a link - /// cycle can cause a row to be cascade-removed as a consequence of being - /// modified. This happens, for example, if two rows, A and B, have strong - /// links to each other, and there are no other strong links to either of - /// them. In this case, if A->B is changed to A->C, then both A and B will - /// be cascade-removed. This can lead to obscure bugs in some applications, - /// such as in the following case: - /// - /// table.set_link(col_ndx_1, row_ndx, ...); - /// table.set_int(col_ndx_2, row_ndx, ...); // Oops, `row_ndx` may no longer refer to the same row - /// - /// To be safe, applications, that may encounter cycles, are advised to - /// adopt the following pattern: - /// - /// Row row = table[row_ndx]; - /// row.set_link(col_ndx_1, ...); - /// if (row) - /// row.set_int(col_ndx_2, ...); // Ok, because we check whether the row has disappeared - /// - /// \param col_ndx The index of the link column (`type_Link` or - /// `type_LinkList`) to be modified. It is an error to specify an index that - /// is greater than, or equal to the number of columns, or to specify the - /// index of a non-link column. - /// - /// \param link_type The type of links the column should store. - void set_link_type(size_t col_ndx, LinkType link_type); - - //@{ - /// Get the descriptor for the specified subtable column. - /// - /// This function provides access to the shared subtable - /// descriptor for the subtables in the specified column. The - /// specified column must be a column whose type is 'table'. The - /// consequences of specifying a column of a different type, or - /// specifying an index that is out of range, are undefined. - /// - /// Note that this function cannot be used with 'mixed' columns, - /// since subtables of that kind have independent dynamic types, - /// and therefore, have independent descriptors. You can only get - /// access to the descriptor of a subtable in a mixed column by - /// first getting access to the subtable itself. - /// - /// \sa is_root() - DescriptorRef get_subdescriptor(size_t column_ndx); - ConstDescriptorRef get_subdescriptor(size_t column_ndx) const; - //@} - - //@{ - /// Returns the parent table descriptor, if any. - /// - /// If this descriptor is the *root descriptor*, then this - /// function returns null. Otherwise it returns the accessor of - /// the parent descriptor. - /// - /// \sa is_root() - DescriptorRef get_parent() noexcept; - ConstDescriptorRef get_parent() const noexcept; - //@} - - //@{ - /// Get the table associated with the root descriptor. - /// - /// \sa get_parent() - /// \sa is_root() - TableRef get_root_table() noexcept; - ConstTableRef get_root_table() const noexcept; - //@} - - //@{ - /// Get the target table associated with the specified link column. This - /// descriptor must be a root descriptor (is_root()), and the specified - /// column must be a link column (`type_Link` or `type_LinkList`). - TableRef get_link_target(size_t col_ndx) noexcept; - ConstTableRef get_link_target(size_t col_ndx) const noexcept; - //@} - - /// Is this a root descriptor? - /// - /// Descriptors of tables with independent dynamic type are root - /// descriptors. Root descriptors are never shared. Tables that - /// are direct members of groups have independent dynamic - /// types. The same is true for free-standing tables and subtables - /// in columns of type 'mixed'. - /// - /// When a table has a column of type 'table', the cells in that - /// column contain subtables. All those subtables have the same - /// dynamic type, and they share a single dynamic type - /// descriptor. Such shared descriptors are never root - /// descriptors. - /// - /// A type descriptor can even be shared by subtables with - /// different parent tables, but only if the parent tables - /// themselves have a shared type descriptor. For example, if a - /// table has a column `foo` of type 'table', and each of the - /// subtables in `foo` has a column `bar` of type 'table', then - /// all the subtables in all the `bar` columns share the same - /// dynamic type descriptor. - /// - /// \sa Table::has_shared_type() - bool is_root() const noexcept; - - /// Determine whether this accessor is still attached. - /// - /// A table descriptor accessor may get detached from the - /// underlying descriptor for various reasons (see below). When it - /// does, it no longer refers to that descriptor, and can no - /// longer be used, except for calling is_attached(). The - /// consequences of calling other methods on a detached accessor - /// are undefined. Descriptor accessors obtained by calling - /// functions in the Realm API are always in the 'attached' - /// state immediately upon return from those functions. - /// - /// A descriptor accessor that is obtained directly from a table - /// becomes detached if the table becomes detached. A shared - /// subtable descriptor accessor that is obtained by a call to - /// get_subdescriptor() becomes detached if the parent descriptor - /// accessor becomes detached, or if the corresponding subtable - /// column is removed. A descriptor accessor does not get detached - /// under any other circumstances. - bool is_attached() const noexcept; - - //@{ - /// \brief Compare two table descriptors. - /// - /// Two table descriptors are equal if they have the same number of columns, - /// and for each column index, the two columns have the same name, data - /// type, and set of attributes. - /// - /// For link columns (`type_Link` and `type_LinkList`), the target table - /// (get_link_target()) of the two columns must be the same. - /// - /// For subtable columns (`type_Table`), the two corresponding - /// subdescriptors must themselves be equal, as if by a recursive call to - /// operator==(). - /// - /// The consequences of comparing a detached descriptor are - /// undefined. - bool operator==(const Descriptor&) const noexcept; - bool operator!=(const Descriptor&) const noexcept; - //@} - - /// If the specified column is optimized to store only unique values, then - /// this function returns the number of unique values currently - /// stored. Otherwise it returns zero. This function is mainly intended for - /// debugging purposes. - size_t get_num_unique_values(size_t column_ndx) const; - - ~Descriptor() noexcept; - -private: - // for initialization through make_shared - struct PrivateTag { - }; - -public: - Descriptor(const PrivateTag&) - : Descriptor() - { - } - -private: - // Table associated with root descriptor. Detached iff null. - TableRef m_root_table; - DescriptorRef m_parent; // Null iff detached or root descriptor. - Spec* m_spec; // Valid if attached. Owned iff valid and `m_parent`. - - // Whenever a subtable descriptor accessor is created, it is - // stored in this map. This ensures that when get_subdescriptor() - // is called to created multiple DescriptorRef objects that - // overlap in time, then they will all refer to the same - // descriptor object. - // - // It also enables the necessary recursive detaching of descriptor - // objects. - struct subdesc_entry { - size_t m_column_ndx; - std::weak_ptr m_subdesc; - subdesc_entry(size_t column_ndx, DescriptorRef); - }; - typedef std::vector subdesc_map; - mutable subdesc_map m_subdesc_map; - - Descriptor() noexcept; - - // Called by the root table if this becomes the root - // descriptor. Otherwise it is called by the descriptor that - // becomes its parent. - // - // Puts this descriptor accessor into the attached state. This - // attaches it to the underlying structure of array nodes. It does - // not establish the parents reference to this descriptor, that is - // the job of the parent. When this function returns, - // is_attached() will return true. - // - // Not idempotent. - // - // The specified table is not allowed to be a subtable with a - // shareable spec. That is, Table::has_shared_spec() must return - // false. - // - // The specified spec must be the spec of the specified table or - // of one of its direct or indirect subtable columns. - // - // When the specified spec is the spec of the root table, the - // parent must be specified as null. When the specified spec is - // not the root spec, a proper parent must be specified. - void attach(Table*, DescriptorRef parent, Spec*) noexcept; - - // Detach accessor from underlying descriptor. Caller must ensure - // that a reference count exists upon return, for example by - // obtaining an extra reference count before the call. - // - // This function is called either by the root table if this is the - // root descriptor, or by the parent descriptor, if it is not. - // - // Puts this descriptor accessor into the detached state. This - // detaches it from the underlying structure of array nodes. It - // also calls detach_subdesc_accessors(). When this function - // returns, is_attached() will return false. - // - // Not idempotent. - void detach() noexcept; - - // Recursively detach all subtable descriptor accessors that - // exist, that is, all subtable descriptor accessors that have - // this descriptor as ancestor. - void detach_subdesc_accessors() noexcept; - - // Record the path in terms of subtable column indexes from the - // root descriptor to this descriptor. If this descriptor is a - // root descriptor, the path is empty. Returns zero if the path is - // too long to fit in the specified buffer. Otherwise the path - // indexes will be stored between `begin_2`and `end`, where - // `begin_2` is the returned pointer. - size_t* record_subdesc_path(size_t* begin, size_t* end) const noexcept; - - // Returns a pointer to the accessor of the specified - // subdescriptor if that accessor exists, otherwise this function - // return null. - DescriptorRef get_subdesc_accessor(size_t column_ndx) noexcept; - - void move_column(size_t from_ndx, size_t to_ndx); - - void adj_insert_column(size_t col_ndx) noexcept; - void adj_erase_column(size_t col_ndx) noexcept; - void adj_move_column(size_t col_ndx_1, size_t col_ndx_2) noexcept; - - friend class util::bind_ptr; - friend class util::bind_ptr; - friend class _impl::DescriptorFriend; -}; - - -// Implementation: - -inline size_t Descriptor::get_column_count() const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_public_column_count(); -} - -inline StringData Descriptor::get_column_name(size_t ndx) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_column_name(ndx); -} - -inline DataType Descriptor::get_column_type(size_t ndx) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_public_column_type(ndx); -} - -inline bool Descriptor::is_nullable(size_t ndx) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_column_attr(ndx) & col_attr_Nullable; -} - -inline size_t Descriptor::get_column_index(StringData name) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_column_index(name); -} - -inline size_t Descriptor::get_column_link_target(size_t column_ndx) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec->get_opposite_link_table_ndx(column_ndx); -} - -inline size_t Descriptor::add_column(DataType type, StringData name, DescriptorRef* subdesc, bool nullable) -{ - size_t col_ndx = m_spec->get_public_column_count(); - insert_column(col_ndx, type, name, subdesc, nullable); // Throws - return col_ndx; -} - -inline void Descriptor::insert_column(size_t col_ndx, DataType type, StringData name, DescriptorRef* subdesc, - bool nullable) -{ - typedef _impl::TableFriend tf; - - if (REALM_UNLIKELY(!is_attached())) - throw LogicError(LogicError::detached_accessor); - if (REALM_UNLIKELY(col_ndx > get_column_count())) - throw LogicError(LogicError::column_index_out_of_range); - if (REALM_UNLIKELY(tf::is_link_type(ColumnType(type)))) - throw LogicError(LogicError::illegal_type); - - LinkTargetInfo invalid_link; - tf::insert_column(*this, col_ndx, type, name, invalid_link, nullable); // Throws - adj_insert_column(col_ndx); - if (subdesc && type == type_Table) - *subdesc = get_subdescriptor(col_ndx); -} - -inline size_t Descriptor::add_column_link(DataType type, StringData name, Table& target, LinkType link_type) -{ - size_t col_ndx = m_spec->get_public_column_count(); - insert_column_link(col_ndx, type, name, target, link_type); // Throws - return col_ndx; -} - -inline void Descriptor::insert_column_link(size_t col_ndx, DataType type, StringData name, Table& target, - LinkType link_type) -{ - typedef _impl::TableFriend tf; - - if (REALM_UNLIKELY(!is_attached() || !target.is_attached())) - throw LogicError(LogicError::detached_accessor); - if (REALM_UNLIKELY(col_ndx > get_column_count())) - throw LogicError(LogicError::column_index_out_of_range); - if (REALM_UNLIKELY(!tf::is_link_type(ColumnType(type)))) - throw LogicError(LogicError::illegal_type); - if (REALM_UNLIKELY(!is_root())) - throw LogicError(LogicError::wrong_kind_of_descriptor); - // Both origin and target must be group-level tables, and in the same group. - Group* origin_group = tf::get_parent_group(*get_root_table()); - Group* target_group = tf::get_parent_group(target); - if (!origin_group || !target_group) - throw LogicError(LogicError::wrong_kind_of_table); - if (origin_group != target_group) - throw LogicError(LogicError::group_mismatch); - - LinkTargetInfo link(&target); - tf::insert_column(*this, col_ndx, type, name, link); // Throws - adj_insert_column(col_ndx); - - tf::set_link_type(*get_root_table(), col_ndx, link_type); // Throws -} - -inline void Descriptor::remove_column(size_t col_ndx) -{ - typedef _impl::TableFriend tf; - - if (REALM_UNLIKELY(!is_attached())) - throw LogicError(LogicError::detached_accessor); - if (REALM_UNLIKELY(col_ndx >= get_column_count())) - throw LogicError(LogicError::column_index_out_of_range); - - tf::erase_column(*this, col_ndx); // Throws - adj_erase_column(col_ndx); -} - -inline void Descriptor::rename_column(size_t col_ndx, StringData name) -{ - typedef _impl::TableFriend tf; - - if (REALM_UNLIKELY(!is_attached())) - throw LogicError(LogicError::detached_accessor); - if (REALM_UNLIKELY(col_ndx >= get_column_count())) - throw LogicError(LogicError::column_index_out_of_range); - - tf::rename_column(*this, col_ndx, name); // Throws -} - -inline void Descriptor::move_column(size_t from_ndx, size_t to_ndx) -{ - REALM_ASSERT(is_attached()); - typedef _impl::TableFriend tf; - tf::move_column(*this, from_ndx, to_ndx); // Throws - adj_move_column(from_ndx, to_ndx); -} - -inline void Descriptor::set_link_type(size_t col_ndx, LinkType link_type) -{ - typedef _impl::TableFriend tf; - - if (REALM_UNLIKELY(!is_attached())) - throw LogicError(LogicError::detached_accessor); - if (REALM_UNLIKELY(col_ndx >= get_column_count())) - throw LogicError(LogicError::column_index_out_of_range); - if (REALM_UNLIKELY(!tf::is_link_type(ColumnType(get_column_type(col_ndx))))) - throw LogicError(LogicError::illegal_type); - - tf::set_link_type(*get_root_table(), col_ndx, link_type); // Throws -} - -inline ConstDescriptorRef Descriptor::get_subdescriptor(size_t column_ndx) const -{ - return const_cast(this)->get_subdescriptor(column_ndx); -} - -inline DescriptorRef Descriptor::get_parent() noexcept -{ - return m_parent; -} - -inline ConstDescriptorRef Descriptor::get_parent() const noexcept -{ - return const_cast(this)->get_parent(); -} - -inline TableRef Descriptor::get_root_table() noexcept -{ - return m_root_table; -} - -inline ConstTableRef Descriptor::get_root_table() const noexcept -{ - return const_cast(this)->get_root_table(); -} - -inline TableRef Descriptor::get_link_target(size_t col_ndx) noexcept -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT(is_root()); - return get_root_table()->get_link_target(col_ndx); -} - -inline ConstTableRef Descriptor::get_link_target(size_t col_ndx) const noexcept -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT(is_root()); - return get_root_table()->get_link_target(col_ndx); -} - -inline bool Descriptor::is_root() const noexcept -{ - return !m_parent; -} - -inline Descriptor::Descriptor() noexcept -{ -} - -inline void Descriptor::attach(Table* table, DescriptorRef parent, Spec* spec) noexcept -{ - REALM_ASSERT(!is_attached()); - REALM_ASSERT(!table->has_shared_type()); - m_root_table.reset(table); - m_parent = parent; - m_spec = spec; -} - -inline bool Descriptor::is_attached() const noexcept -{ - return bool(m_root_table); -} - -inline Descriptor::subdesc_entry::subdesc_entry(size_t n, DescriptorRef d) - : m_column_ndx(n) - , m_subdesc(d) -{ -} - -inline bool Descriptor::operator==(const Descriptor& d) const noexcept -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT(d.is_attached()); - return *m_spec == *d.m_spec; -} - -inline bool Descriptor::operator!=(const Descriptor& d) const noexcept -{ - return !(*this == d); -} - -// The purpose of this class is to give internal access to some, but -// not all of the non-public parts of the Descriptor class. -class _impl::DescriptorFriend { -public: - static DescriptorRef create() - { - return std::make_shared(Descriptor::PrivateTag()); // Throws - } - - static void attach(Descriptor& desc, Table* table, DescriptorRef parent, Spec* spec) noexcept - { - desc.attach(table, parent, spec); - } - - static void detach(Descriptor& desc) noexcept - { - desc.detach(); - } - - static Table& get_root_table(Descriptor& desc) noexcept - { - return *desc.m_root_table; - } - - static const Table& get_root_table(const Descriptor& desc) noexcept - { - return *desc.m_root_table; - } - - static Spec& get_spec(Descriptor& desc) noexcept - { - return *desc.m_spec; - } - - static const Spec& get_spec(const Descriptor& desc) noexcept - { - return *desc.m_spec; - } - - static size_t* record_subdesc_path(const Descriptor& desc, size_t* begin, size_t* end) noexcept - { - return desc.record_subdesc_path(begin, end); - } - - static DescriptorRef get_subdesc_accessor(Descriptor& desc, size_t column_ndx) noexcept - { - return desc.get_subdesc_accessor(column_ndx); - } - - static void move_column(Descriptor& desc, size_t from_ndx, size_t to_ndx) - { - return desc.move_column(from_ndx, to_ndx); - } - - static void adj_insert_column(Descriptor& desc, size_t col_ndx) noexcept - { - desc.adj_insert_column(col_ndx); - } - - static void adj_erase_column(Descriptor& desc, size_t col_ndx) noexcept - { - desc.adj_erase_column(col_ndx); - } - - static void adj_move_column(Descriptor& desc, size_t col_ndx_1, size_t col_ndx_2) noexcept - { - desc.adj_move_column(col_ndx_1, col_ndx_2); - } -}; - -} // namespace realm - -#endif // REALM_DESCRIPTOR_HPP diff --git a/Example/Pods/Realm/include/core/realm/descriptor_fwd.hpp b/Example/Pods/Realm/include/core/realm/descriptor_fwd.hpp deleted file mode 100644 index 2937724..0000000 --- a/Example/Pods/Realm/include/core/realm/descriptor_fwd.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_DESCRIPTOR_FWD_HPP -#define REALM_DESCRIPTOR_FWD_HPP - -#include - - -namespace realm { - -class Descriptor; -typedef std::shared_ptr DescriptorRef; -typedef std::shared_ptr ConstDescriptorRef; - -} // namespace realm - -#endif // REALM_DESCRIPTOR_FWD_HPP diff --git a/Example/Pods/Realm/include/core/realm/disable_sync_to_disk.hpp b/Example/Pods/Realm/include/core/realm/disable_sync_to_disk.hpp deleted file mode 100644 index f642d6f..0000000 --- a/Example/Pods/Realm/include/core/realm/disable_sync_to_disk.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_DISABLE_SYNC_TO_DISK_HPP -#define REALM_DISABLE_SYNC_TO_DISK_HPP - -#include - -namespace realm { - -/// Completely disable synchronization with storage device to speed up unit -/// testing. This is an unsafe mode of operation, and should never be used in -/// production. This function is thread safe. -void disable_sync_to_disk(); - -/// Returns true after disable_sync_to_disk() has been called. This function is -/// thread safe. -bool get_disable_sync_to_disk() noexcept; - -} // namespace realm - -#endif // REALM_DISABLE_SYNC_TO_DISK_HPP diff --git a/Example/Pods/Realm/include/core/realm/exceptions.hpp b/Example/Pods/Realm/include/core/realm/exceptions.hpp deleted file mode 100644 index a2dcd55..0000000 --- a/Example/Pods/Realm/include/core/realm/exceptions.hpp +++ /dev/null @@ -1,270 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_EXCEPTIONS_HPP -#define REALM_EXCEPTIONS_HPP - -#include - -#include - -namespace realm { - -/// Thrown by various functions to indicate that a specified table does not -/// exist. -class NoSuchTable : public std::exception { -public: - const char* what() const noexcept override; -}; - - -/// Thrown by various functions to indicate that a specified table name is -/// already in use. -class TableNameInUse : public std::exception { -public: - const char* what() const noexcept override; -}; - - -// Thrown by functions that require a table to **not** be the target of link -// columns, unless those link columns are part of the table itself. -class CrossTableLinkTarget : public std::exception { -public: - const char* what() const noexcept override; -}; - - -/// Thrown by various functions to indicate that the dynamic type of a table -/// does not match a particular other table type (dynamic or static). -class DescriptorMismatch : public std::exception { -public: - const char* what() const noexcept override; -}; - - -/// The \c FileFormatUpgradeRequired exception can be thrown by the \c -/// SharedGroup constructor when opening a database that uses a deprecated file -/// format, and the user has indicated he does not want automatic upgrades to -/// be performed. This exception indicates that until an upgrade of the file -/// format is performed, the database will be unavailable for read or write -/// operations. -class FileFormatUpgradeRequired : public std::exception { -public: - const char* what() const noexcept override; -}; - - -/// Thrown when a sync agent attempts to join a session in which there is -/// already a sync agent. A session may only contain one sync agent at any given -/// time. -class MultipleSyncAgents : public std::exception { -public: - const char* what() const noexcept override; -}; - - -/// Thrown when memory can no longer be mapped to. When mmap/remap fails. -class AddressSpaceExhausted : public std::runtime_error { -public: - AddressSpaceExhausted(const std::string& msg); - /// runtime_error::what() returns the msg provided in the constructor. -}; - - -/// The \c LogicError exception class is intended to be thrown only when -/// applications (or bindings) violate rules that are stated (or ought to have -/// been stated) in the documentation of the public API, and only in cases -/// where the violation could have been easily and efficiently predicted by the -/// application. In other words, this exception class is for the cases where -/// the error is due to incorrect use of the public API. -/// -/// This class is not supposed to be caught by applications. It is not even -/// supposed to be considered part of the public API, and therefore the -/// documentation of the public API should **not** mention the \c LogicError -/// exception class by name. Note how this contrasts with other exception -/// classes, such as \c NoSuchTable, which are part of the public API, and are -/// supposed to be mentioned in the documentation by name. The \c LogicError -/// exception is part of Realm's private API. -/// -/// In other words, the \c LogicError class should exclusively be used in -/// replacement (or in addition to) asserts (debug or not) in order to -/// guarantee program interruption, while still allowing for complete -/// test-cases to be written and run. -/// -/// To this effect, the special `CHECK_LOGIC_ERROR()` macro is provided as a -/// test framework plugin to allow unit tests to check that the functions in -/// the public API do throw \c LogicError when rules are violated. -/// -/// The reason behind hiding this class from the public API is to prevent users -/// from getting used to the idea that "Undefined Behaviour" equates a specific -/// exception being thrown. The whole point of properly documenting "Undefined -/// Behaviour" cases is to help the user know what the limits are, without -/// constraining the database to handle every and any use-case thrown at it. -/// -/// FIXME: This exception class should probably be moved to the `_impl` -/// namespace, in order to avoid some confusion. -class LogicError : public std::exception { -public: - enum ErrorKind { - string_too_big, - binary_too_big, - table_name_too_long, - column_name_too_long, - table_index_out_of_range, - row_index_out_of_range, - column_index_out_of_range, - string_position_out_of_range, - link_index_out_of_range, - bad_version, - illegal_type, - - /// Indicates that an argument has a value that is illegal in combination - /// with another argument, or with the state of an involved object. - illegal_combination, - - /// Indicates a data type mismatch, such as when `Table::find_pkey_int()` is - /// called and the type of the primary key is not `type_Int`. - type_mismatch, - - /// Indicates that two involved tables are not in the same group. - group_mismatch, - - /// Indicates that an involved descriptor is of the wrong kind, i.e., if - /// it is a subtable descriptor, and the function requires a root table - /// descriptor. - wrong_kind_of_descriptor, - - /// Indicates that an involved table is of the wrong kind, i.e., if it - /// is a subtable, and the function requires a root table, or if it is a - /// free-standing table, and the function requires a group-level table. - wrong_kind_of_table, - - /// Indicates that an involved accessor is was detached, i.e., was not - /// attached to an underlying object. - detached_accessor, - - /// Indicates that a specified row index of a target table (a link) is - /// out of range. This is used for disambiguation in cases such as - /// Table::set_link() where one specifies both a row index of the origin - /// table, and a row index of the target table. - target_row_index_out_of_range, - - // Indicates that an involved column lacks a search index. - no_search_index, - - /// Indicates that a modification was attempted that would have produced a - /// duplicate primary value. - unique_constraint_violation, - - /// User attempted to insert null in non-nullable column - column_not_nullable, - - /// Group::open() is called on a group accessor that is already in the - /// attached state. Or Group::open() or Group::commit() is called on a - /// group accessor that is managed by a SharedGroup object. - wrong_group_state, - - /// No active transaction on a particular SharedGroup object (e.g., - /// SharedGroup::commit()), or the active transaction on the SharedGroup - /// object is of the wrong type (read/write), or an attampt was made to - /// initiate a new transaction while one is already in progress on the - /// same SharedGroup object. - wrong_transact_state, - - /// Attempted use of a continuous transaction through a SharedGroup - /// object with no history. See Replication::get_history(). - no_history, - - /// Durability setting (as passed to the SharedGroup constructor) was - /// not consistent across the session. - mixed_durability, - - /// History type (as specified by the Replication implementation passed - /// to the SharedGroup constructor) was not consistent across the - /// session. - mixed_history_type, - - /// Adding rows to a table with no columns is not supported. - table_has_no_columns - }; - - LogicError(ErrorKind message); - - const char* what() const noexcept override; - ErrorKind kind() const noexcept; - -private: - ErrorKind m_kind; -}; - - -// Implementation: - -// LCOV_EXCL_START (Wording of what() strings are not to be tested) - -inline const char* NoSuchTable::what() const noexcept -{ - return "No such table exists"; -} - -inline const char* TableNameInUse::what() const noexcept -{ - return "The specified table name is already in use"; -} - -inline const char* CrossTableLinkTarget::what() const noexcept -{ - return "Table is target of cross-table link columns"; -} - -inline const char* DescriptorMismatch::what() const noexcept -{ - return "Table descriptor mismatch"; -} - -inline const char* FileFormatUpgradeRequired::what() const noexcept -{ - return "Database upgrade required but prohibited"; -} - -inline const char* MultipleSyncAgents::what() const noexcept -{ - return "Multiple sync agents attempted to join the same session"; -} - -// LCOV_EXCL_STOP - -inline AddressSpaceExhausted::AddressSpaceExhausted(const std::string& msg) - : std::runtime_error(msg) -{ -} - -inline LogicError::LogicError(LogicError::ErrorKind k) - : m_kind(k) -{ -} - -inline LogicError::ErrorKind LogicError::kind() const noexcept -{ - return m_kind; -} - - -} // namespace realm - -#endif // REALM_EXCEPTIONS_HPP diff --git a/Example/Pods/Realm/include/core/realm/group.hpp b/Example/Pods/Realm/include/core/realm/group.hpp deleted file mode 100644 index 490dd26..0000000 --- a/Example/Pods/Realm/include/core/realm/group.hpp +++ /dev/null @@ -1,1371 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_GROUP_HPP -#define REALM_GROUP_HPP - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - -class SharedGroup; -namespace _impl { -class GroupFriend; -class TransactLogConvenientEncoder; -class TransactLogParser; -} - - -/// A group is a collection of named tables. -/// -/// Tables occur in the group in an unspecified order, but an order that -/// generally remains fixed. The order is guaranteed to remain fixed between two -/// points in time if no tables are added to, or removed from the group during -/// that time. When tables are added to, or removed from the group, the order -/// may change arbitrarily. -/// -/// If `table` is a table accessor attached to a group-level table, and `group` -/// is a group accessor attached to the group, then the following is guaranteed, -/// even after a change in the table order: -/// -/// \code{.cpp} -/// -/// table == group.get_table(table.get_index_in_group()) -/// -/// \endcode -/// -class Group : private Table::Parent { -public: - /// Construct a free-standing group. This group instance will be - /// in the attached state, but neither associated with a file, nor - /// with an external memory buffer. - Group(); - - enum OpenMode { - /// Open in read-only mode. Fail if the file does not already exist. - mode_ReadOnly, - /// Open in read/write mode. Create the file if it doesn't exist. - mode_ReadWrite, - /// Open in read/write mode. Fail if the file does not already exist. - mode_ReadWriteNoCreate - }; - - /// Equivalent to calling open(const std::string&, const char*, OpenMode) - /// on an unattached group accessor. - explicit Group(const std::string& file, const char* encryption_key = nullptr, OpenMode = mode_ReadOnly); - - /// Equivalent to calling open(BinaryData, bool) on an unattached - /// group accessor. Note that if this constructor throws, the - /// ownership of the memory buffer will remain with the caller, - /// regardless of whether \a take_ownership is set to `true` or - /// `false`. - explicit Group(BinaryData, bool take_ownership = true); - - struct unattached_tag { - }; - - /// Create a Group instance in its unattached state. It may then - /// be attached to a database file later by calling one of the - /// open() methods. You may test whether this instance is - /// currently in its attached state by calling - /// is_attached(). Calling any other method (except the - /// destructor) while in the unattached state has undefined - /// behavior. - Group(unattached_tag) noexcept; - - // FIXME: Implement a proper copy constructor (fairly trivial). - Group(const Group&) = delete; - - ~Group() noexcept override; - - /// Attach this Group instance to the specified database file. - /// - /// By default, the specified file is opened in read-only mode - /// (mode_ReadOnly). This allows opening a file even when the - /// caller lacks permission to write to that file. The opened - /// group may still be modified freely, but the changes cannot be - /// written back to the same file using the commit() function. An - /// attempt to do that, will cause an exception to be thrown. When - /// opening in read-only mode, it is an error if the specified - /// file does not already exist in the file system. - /// - /// Alternatively, the file can be opened in read/write mode - /// (mode_ReadWrite). This allows use of the commit() function, - /// but, of course, it also requires that the caller has - /// permission to write to the specified file. When opening in - /// read-write mode, an attempt to create the specified file will - /// be made, if it does not already exist in the file system. - /// - /// In any case, if the file already exists, it must contain a - /// valid Realm database. In many cases invalidity will be - /// detected and cause the InvalidDatabase exception to be thrown, - /// but you should not rely on it. - /// - /// Note that changes made to the database via a Group instance - /// are not automatically committed to the specified file. You - /// may, however, at any time, explicitly commit your changes by - /// calling the commit() method, provided that the specified - /// open-mode is not mode_ReadOnly. Alternatively, you may call - /// write() to write the entire database to a new file. Writing - /// the database to a new file does not end, or in any other way - /// change the association between the Group instance and the file - /// that was specified in the call to open(). - /// - /// A file that is passed to Group::open(), may not be modified by - /// a third party until after the Group object is - /// destroyed. Behavior is undefined if a file is modified by a - /// third party while any Group object is associated with it. - /// - /// Calling open() on a Group instance that is already in the - /// attached state has undefined behavior. - /// - /// Accessing a Realm database file through manual construction - /// of a Group object does not offer any level of thread safety or - /// transaction safety. When any of those kinds of safety are a - /// concern, consider using a SharedGroup instead. When accessing - /// a database file in read/write mode through a manually - /// constructed Group object, it is entirely the responsibility of - /// the application that the file is not accessed in any way by a - /// third party during the life-time of that group object. It is, - /// on the other hand, safe to concurrently access a database file - /// by multiple manually created Group objects, as long as all of - /// them are opened in read-only mode, and there is no other party - /// that modifies the file concurrently. - /// - /// Do not call this function on a group instance that is managed - /// by a shared group. Doing so will result in undefined behavior. - /// - /// Even if this function throws, it may have the side-effect of - /// creating the specified file, and the file may get left behind - /// in an invalid state. Of course, this can only happen if - /// read/write mode (mode_ReadWrite) was requested, and the file - /// did not already exist. - /// - /// \param file File system path to a Realm database file. - /// - /// \param encryption_key 32-byte key used to encrypt and decrypt - /// the database file, or nullptr to disable encryption. - /// - /// \param mode Specifying a mode that is not mode_ReadOnly - /// requires that the specified file can be opened in read/write - /// mode. In general there is no reason to open a group in - /// read/write mode unless you want to be able to call - /// Group::commit(). - /// - /// \throw util::File::AccessError If the file could not be - /// opened. If the reason corresponds to one of the exception - /// types that are derived from util::File::AccessError, the - /// derived exception type is thrown. Note that InvalidDatabase is - /// among these derived exception types. - void open(const std::string& file, const char* encryption_key = nullptr, OpenMode mode = mode_ReadOnly); - - /// Attach this Group instance to the specified memory buffer. - /// - /// This is similar to constructing a group from a file except - /// that in this case the database is assumed to be stored in the - /// specified memory buffer. - /// - /// If \a take_ownership is `true`, you pass the ownership of the - /// specified buffer to the group. In this case the buffer will - /// eventually be freed using std::free(), so the buffer you pass, - /// must have been allocated using std::malloc(). - /// - /// On the other hand, if \a take_ownership is set to `false`, it - /// is your responsibility to keep the memory buffer alive during - /// the lifetime of the group, and in case the buffer needs to be - /// deallocated afterwards, that is your responsibility too. - /// - /// If this function throws, the ownership of the memory buffer - /// will remain with the caller, regardless of whether \a - /// take_ownership is set to `true` or `false`. - /// - /// Calling open() on a Group instance that is already in the - /// attached state has undefined behavior. - /// - /// Do not call this function on a group instance that is managed - /// by a shared group. Doing so will result in undefined behavior. - /// - /// \throw InvalidDatabase If the specified buffer does not appear - /// to contain a valid database. - void open(BinaryData, bool take_ownership = true); - - /// A group may be created in the unattached state, and then later - /// attached to a file with a call to open(). Calling any method - /// other than open(), and is_attached() on an unattached instance - /// results in undefined behavior. - bool is_attached() const noexcept; - - /// Returns true if, and only if the number of tables in this - /// group is zero. - bool is_empty() const noexcept; - - /// Returns the number of tables in this group. - size_t size() const noexcept; - - /// \defgroup group_table_access Table Accessors - /// - /// has_table() returns true if, and only if this group contains a table - /// with the specified name. - /// - /// find_table() returns the index of the first table in this group with the - /// specified name, or `realm::not_found` if this group does not contain a - /// table with the specified name. - /// - /// get_table_name() returns the name of table at the specified index. - /// - /// The versions of get_table(), that accepts a \a name argument, return the - /// first table with the specified name, or null if no such table exists. - /// - /// add_table() adds a table with the specified name to this group. It - /// throws TableNameInUse if \a require_unique_name is true and \a name - /// clashes with the name of an existing table. If \a require_unique_name is - /// false, it is possible to add more than one table with the same - /// name. Whenever a table is added, the order of the preexisting tables may - /// change arbitrarily, and the new table may not end up as the last one - /// either. But know that you can always call Table::get_index_in_group() on - /// the returned table accessor to find out at which index it ends up. - /// - /// get_or_add_table() checks if a table exists in this group with the specified - /// name. If it doesn't exist, a table is created. - /// - /// get_or_insert_table() works slightly differently from get_or_add_table(), - /// in that it considers the position of the requested table as part of that - /// table's identifying "key", in addition to the name. - /// - /// remove_table() removes the specified table from this group. A table can - /// be removed only when it is not the target of a link column of a - /// different table. Whenever a table is removed, the order of the remaining - /// tables may change arbitrarily. - /// - /// rename_table() changes the name of a preexisting table. If \a - /// require_unique_name is false, it becomes possible to have more than one - /// table with a given name in a single group. - /// - /// The template functions work exactly like their non-template namesakes - /// except as follows: The template versions of get_table() and - /// get_or_add_table() throw DescriptorMismatch if the dynamic type of the - /// specified table does not match the statically specified custom table - /// type. The template versions of add_table() and get_or_add_table() set - /// the dynamic type (descriptor) to match the statically specified custom - /// table type. - /// - /// \tparam T An instance of the BasicTable class template. - /// - /// \param index Index of table in this group. - /// - /// \param name Name of table. All strings are valid table names as long as - /// they are valid UTF-8 encodings and the number of bytes does not exceed - /// `max_table_name_length`. A call to add_table() or get_or_add_table() - /// with a name that is longer than `max_table_name_length` will cause an - /// exception to be thrown. - /// - /// \param new_name New name for preexisting table. - /// - /// \param require_unique_name When set to true (the default), it becomes - /// impossible to add a table with a name that is already in use, or to - /// rename a table to a name that is already in use. - /// - /// \param was_added When specified, the boolean variable is set to true if - /// the table was added, and to false otherwise. If the function throws, the - /// boolean variable retains its original value. - /// - /// \return get_table(), add_table(), and get_or_add_table() return a table - /// accessor attached to the requested (or added) table. get_table() may - /// return null. - /// - /// \throw DescriptorMismatch Thrown by get_table() and get_or_add_table() - /// tf the dynamic table type does not match the statically specified custom - /// table type (\a T). - /// - /// \throw NoSuchTable Thrown by remove_table() and rename_table() if there - /// is no table with the specified \a name. - /// - /// \throw TableNameInUse Thrown by add_table() if \a require_unique_name is - /// true and \a name clashes with the name of a preexisting table. Thrown by - /// rename_table() if \a require_unique_name is true and \a new_name clashes - /// with the name of a preexisting table. - /// - /// \throw CrossTableLinkTarget Thrown by remove_table() if the specified - /// table is the target of a link column of a different table. - /// - //@{ - - static const size_t max_table_name_length = 63; - - bool has_table(StringData name) const noexcept; - size_t find_table(StringData name) const noexcept; - StringData get_table_name(size_t table_ndx) const; - - TableRef get_table(size_t index); - ConstTableRef get_table(size_t index) const; - - TableRef get_table(StringData name); - ConstTableRef get_table(StringData name) const; - - TableRef add_table(StringData name, bool require_unique_name = true); - TableRef insert_table(size_t index, StringData name, bool require_unique_name = true); - TableRef get_or_add_table(StringData name, bool* was_added = nullptr); - TableRef get_or_insert_table(size_t index, StringData name, bool* was_added = nullptr); - - template - BasicTableRef get_table(size_t index); - - template - BasicTableRef get_table(size_t index) const; - - template - BasicTableRef get_table(StringData name); - - template - BasicTableRef get_table(StringData name) const; - - template - BasicTableRef add_table(StringData name, bool require_unique_name = true); - - template - BasicTableRef insert_table(size_t index, StringData name, bool require_unique_name = true); - - template - BasicTableRef get_or_add_table(StringData name, bool* was_added = nullptr); - - template - BasicTableRef get_or_insert_table(size_t index, StringData name, bool* was_added = nullptr); - - void remove_table(size_t index); - void remove_table(StringData name); - - void rename_table(size_t index, StringData new_name, bool require_unique_name = true); - void rename_table(StringData name, StringData new_name, bool require_unique_name = true); - - //@} - - /// Move the table at \a from_index such that it ends up at \a - /// to_index. Other tables are shifted as necessary in such a way that their - /// order is preserved. - /// - /// Note that \a to_index is the desired final index of the moved table, - /// therefore, `move_table(1,1)` is a no-op, while `move_table(1,2)` moves - /// the table at index 1 by one position, such that it ends up at index 2. A - /// side-effect of that, is that the table, that was originally at index 2, - /// is moved to index 1. - void move_table(size_t from_index, size_t to_index); - - // Serialization - - /// Write this database to the specified output stream. - /// - /// \param out The destination output stream to write to. - /// - /// \param pad If true, the file is padded to ensure the footer is aligned - /// to the end of a page - void write(std::ostream& out, bool pad = false) const; - - /// Write this database to a new file. It is an error to specify a - /// file that already exists. This is to protect against - /// overwriting a database file that is currently open, which - /// would cause undefined behaviour. - /// - /// \param file A filesystem path. - /// - /// \param encryption_key 32-byte key used to encrypt the database file, - /// or nullptr to disable encryption. - /// - /// \throw util::File::AccessError If the file could not be - /// opened. If the reason corresponds to one of the exception - /// types that are derived from util::File::AccessError, the - /// derived exception type is thrown. In particular, - /// util::File::Exists will be thrown if the file exists already. - void write(const std::string& file, const char* encryption_key = nullptr) const; - - /// Write this database to a memory buffer. - /// - /// Ownership of the returned buffer is transferred to the - /// caller. The memory will have been allocated using - /// std::malloc(). - BinaryData write_to_mem() const; - - /// Commit changes to the attached file. This requires that the - /// attached file is opened in read/write mode. - /// - /// Calling this function on an unattached group, a free-standing - /// group, a group whose attached file is opened in read-only - /// mode, a group that is attached to a memory buffer, or a group - /// that is managed by a shared group, is an error and will result - /// in undefined behavior. - /// - /// Table accesors will remain valid across the commit. Note that - /// this is not the case when working with proper transactions. - void commit(); - - //@{ - /// Some operations on Tables in a Group can cause indirect changes to other - /// fields, including in other Tables in the same Group. Specifically, - /// removing a row will set any links to that row to null, and if it had the - /// last strong links to other rows, will remove those rows. When this - /// happens, The cascade notification handler will be called with a - /// CascadeNotification containing information about what indirect changes - /// will occur, before any changes are made. - /// - /// has_cascade_notification_handler() returns true if and only if there is - /// currently a non-null notification handler registered. - /// - /// set_cascade_notification_handler() replaces the current handler (if any) - /// with the passed in handler. Pass in nullptr to remove the current handler - /// without registering a new one. - /// - /// CascadeNotification contains a vector of rows which will be removed and - /// a vector of links which will be set to null (or removed, for entries in - /// LinkLists). - struct CascadeNotification { - struct row { - /// Non-zero iff the removal of this row is ordered - /// (Table::remove()), as opposed to ordered - /// (Table::move_last_over()). Implicit removals are always - /// unordered. - /// - /// This flag does not take part in comparisons (operator==() and - /// operator<()). - size_t is_ordered_removal : 1; - - /// Index within group of a group-level table. - size_t table_ndx : std::numeric_limits::digits - 1; - - /// Row index which will be removed. - size_t row_ndx; - - row() - : is_ordered_removal(0) - { - } - - bool operator==(const row&) const noexcept; - bool operator!=(const row&) const noexcept; - - /// Trivial lexicographic order - bool operator<(const row&) const noexcept; - }; - - struct link { - const Table* origin_table; ///< A group-level table. - size_t origin_col_ndx; ///< Link column being nullified. - size_t origin_row_ndx; ///< Row in column being nullified. - /// The target row index which is being removed. Mostly relevant for - /// LinkList (to know which entries are being removed), but also - /// valid for Link. - size_t old_target_row_ndx; - }; - - /// A sorted list of rows which will be removed by the current operation. - std::vector rows; - - /// An unordered list of links which will be nullified by the current - /// operation. - std::vector links; - }; - - bool has_cascade_notification_handler() const noexcept; - void set_cascade_notification_handler(std::function new_handler) noexcept; - - //@} - - //@{ - /// During sync operation, schema changes may happen at runtime as connected - /// clients update their schema as part of an app update. Since this is a - /// relatively rare event, no attempt is made at limiting the amount of work - /// the handler is required to do to update its information about table and - /// column indices (i.e., all table and column indices must be recalculated). - /// - /// At the time of writing, only additive schema changes may occur in that - /// scenario. - /// - /// has_schema_change_notification_handler() returns true iff there is currently - /// a non-null notification handler registered. - /// - /// set_schema_change_notification_handler() replaces the current handler (if any) - /// with the passed in handler. Pass in nullptr to remove the current handler - /// without registering a new one. - - bool has_schema_change_notification_handler() const noexcept; - void set_schema_change_notification_handler(std::function new_handler) noexcept; - - //@} - - // Conversion - template - void to_json(S& out, size_t link_depth = 0, std::map* renames = nullptr) const; - void to_string(std::ostream& out) const; - - /// Compare two groups for equality. Two groups are equal if, and - /// only if, they contain the same tables in the same order, that - /// is, for each table T at index I in one of the groups, there is - /// a table at index I in the other group that is equal to T. - /// Tables are equal if they have the same content and the same table name. - bool operator==(const Group&) const; - - /// Compare two groups for inequality. See operator==(). - bool operator!=(const Group& g) const - { - return !(*this == g); - } - - void verify() const; -#ifdef REALM_DEBUG - void print() const; - void print_free() const; - MemStats stats(); - void enable_mem_diagnostics(bool enable = true) - { - m_alloc.enable_debug(enable); - } - void to_dot(std::ostream&) const; - void to_dot() const; // To std::cerr (for GDB) - void to_dot(const char* file_path) const; -#endif - -private: - SlabAlloc m_alloc; - - /// `m_top` is the root node (or top array) of the Realm, and has the - /// following layout: - /// - ///
-    ///
-    ///   slot  value
-    ///   -----------------------
-    ///   1st   m_table_names
-    ///   2nd   m_tables
-    ///   3rd   Logical file size
-    ///   4th   GroupWriter::m_free_positions (optional)
-    ///   5th   GroupWriter::m_free_lengths   (optional)
-    ///   6th   GroupWriter::m_free_versions  (optional)
-    ///   7th   Transaction number / version  (optional)
-    ///   8th   In-Realm history type         (optional)
-    ///   9th   In-Realm history ref          (optional)
-    ///
-    /// 
- /// - /// The 'in-Realm history type' slot stores a value of - /// Replication::HistoryType, although never - /// Replication::hist_OutOfRealm. For more information about that, see - /// Replication::get_history_type(). - /// - /// The first three entries are mandatory. In files created by - /// Group::write(), none of the optional entries are present and the size of - /// `m_top` is 3. In files updated by Group::commit(), the 4th and 5th entry - /// is present, and the size of `m_top` is 5. In files updated by way of a - /// transaction (SharedGroup::commit()), the 4th, 5th, 6th, and 7th entry is - /// present, and the size of `m_top` is 7. In files that contain a changeset - /// history, the 8th and 9th entry is present. - /// - /// When a group accessor is attached to a newly created file or an empty - /// memory buffer where there is no top array yet, `m_top`, `m_tables`, and - /// `m_table_names` with be left in the detached state until the initiation - /// of the first write transaction. In particular, they will remain in the - /// detached state during read transactions that precede the first write - /// transaction. - Array m_top; - ArrayInteger m_tables; - ArrayString m_table_names; - - typedef std::vector table_accessors; - mutable table_accessors m_table_accessors; - - bool m_attached = false; - const bool m_is_shared; - - std::function m_notify_handler; - std::function m_schema_change_handler; - - struct shared_tag { - }; - Group(shared_tag) noexcept; - - void init_array_parents() noexcept; - - /// If `top_ref` is not zero, attach this group accessor to the specified - /// underlying node structure. If `top_ref` is zero and \a - /// create_group_when_missing is true, create a new node structure that - /// represents an empty group, and attach this group accessor to it. It is - /// an error to call this function on an already attached group accessor. - void attach(ref_type top_ref, bool create_group_when_missing); - - /// Detach this group accessor from the underlying node structure. If this - /// group accessors is already in the detached state, this function does - /// nothing (idempotency). - void detach() noexcept; - - /// \param writable Must be set to true when, and only when attaching for a - /// write transaction. - void attach_shared(ref_type new_top_ref, size_t new_file_size, bool writable); - - void create_empty_group(); - - void reset_free_space_tracking(); - - void remap(size_t new_file_size); - void remap_and_update_refs(ref_type new_top_ref, size_t new_file_size); - - /// Recursively update refs stored in all cached array - /// accessors. This includes cached array accessors in any - /// currently attached table accessors. This ensures that the - /// group instance itself, as well as any attached table accessor - /// that exists across Group::commit() will remain valid. This - /// function is not appropriate for use in conjunction with - /// commits via shared group. - void update_refs(ref_type top_ref, size_t old_baseline) noexcept; - - // Overriding method in ArrayParent - void update_child_ref(size_t, ref_type) override; - - // Overriding method in ArrayParent - ref_type get_child_ref(size_t) const noexcept override; - - // Overriding method in Table::Parent - StringData get_child_name(size_t) const noexcept override; - - // Overriding method in Table::Parent - void child_accessor_destroyed(Table*) noexcept override; - - // Overriding method in Table::Parent - Group* get_parent_group() noexcept override; - - class TableWriter; - class DefaultTableWriter; - - static void write(std::ostream&, const Allocator&, TableWriter&, bool no_top_array, bool pad_for_encryption, - uint_fast64_t version_number); - - typedef void (*DescSetter)(Table&); - typedef bool (*DescMatcher)(const Spec&); - - Table* do_get_table(size_t table_ndx, DescMatcher desc_matcher); - const Table* do_get_table(size_t table_ndx, DescMatcher desc_matcher) const; - Table* do_get_table(StringData name, DescMatcher desc_matcher); - const Table* do_get_table(StringData name, DescMatcher desc_matcher) const; - Table* do_insert_table(size_t, StringData name, DescSetter desc_setter, bool require_unique_name); - Table* do_insert_table(size_t, StringData name, DescSetter desc_setter); - Table* do_get_or_add_table(StringData name, DescMatcher desc_matcher, DescSetter setter, bool* was_added); - Table* do_get_or_insert_table(size_t, StringData name, DescMatcher desc_matcher, DescSetter desc_setter, - bool* was_added); - - void create_and_insert_table(size_t new_table_ndx, StringData name); - Table* create_table_accessor(size_t table_ndx); - - void detach_table_accessors() noexcept; // Idempotent - - void mark_all_table_accessors() noexcept; - - void write(const std::string& file, const char* encryption_key, uint_fast64_t version_number) const; - void write(util::File& file, const char* encryption_key, uint_fast64_t version_number) const; - void write(std::ostream&, bool pad, uint_fast64_t version_numer) const; - - Replication* get_replication() const noexcept; - void set_replication(Replication*) noexcept; - class TransactAdvancer; - void advance_transact(ref_type new_top_ref, size_t new_file_size, _impl::NoCopyInputStream&); - void refresh_dirty_accessors(); - template - void update_table_indices(F&& map_function); - - int get_file_format_version() const noexcept; - void set_file_format_version(int) noexcept; - int get_committed_file_format_version() const noexcept; - - /// The specified history type must be a value of Replication::HistoryType. - static int get_target_file_format_version_for_session(int current_file_format_version, int history_type) noexcept; - - /// Must be called from within a write transaction - void upgrade_file_format(int target_file_format_version); - - std::pair get_to_dot_parent(size_t ndx_in_parent) const override; - - void send_cascade_notification(const CascadeNotification& notification) const; - void send_schema_change_notification() const; - - static void get_version_and_history_type(const Array& top, _impl::History::version_type& version, - int& history_type) noexcept; - static ref_type get_history_ref(const Array& top) noexcept; - void set_history_parent(Array& history_root) noexcept; - void prepare_history_parent(Array& history_root, int history_type); - - friend class Table; - friend class GroupWriter; - friend class SharedGroup; - friend class _impl::GroupFriend; - friend class _impl::TransactLogConvenientEncoder; - friend class _impl::TransactLogParser; - friend class Replication; - friend class TrivialReplication; -}; - - -// Implementation - -inline Group::Group(const std::string& file, const char* key, OpenMode mode) - : m_alloc() // Throws - , m_top(m_alloc) - , m_tables(m_alloc) - , m_table_names(m_alloc) - , m_is_shared(false) -{ - init_array_parents(); - - open(file, key, mode); // Throws -} - -inline Group::Group(BinaryData buffer, bool take_ownership) - : m_alloc() // Throws - , m_top(m_alloc) - , m_tables(m_alloc) - , m_table_names(m_alloc) - , m_is_shared(false) -{ - init_array_parents(); - open(buffer, take_ownership); // Throws -} - -inline Group::Group(unattached_tag) noexcept - : m_alloc() - , // Throws - m_top(m_alloc) - , m_tables(m_alloc) - , m_table_names(m_alloc) - , m_is_shared(false) -{ - init_array_parents(); -} - -inline Group* Group::get_parent_group() noexcept -{ - return this; -} - -inline Group::Group(shared_tag) noexcept - : m_alloc() - , // Throws - m_top(m_alloc) - , m_tables(m_alloc) - , m_table_names(m_alloc) - , m_is_shared(true) -{ - init_array_parents(); -} - -inline bool Group::is_attached() const noexcept -{ - return m_attached; -} - -inline bool Group::is_empty() const noexcept -{ - if (!is_attached()) - return false; - if (m_table_names.is_attached()) - return m_table_names.is_empty(); - return true; -} - -inline size_t Group::size() const noexcept -{ - if (!is_attached()) - return 0; - if (m_table_names.is_attached()) - return m_table_names.size(); - return 0; -} - -inline StringData Group::get_table_name(size_t table_ndx) const -{ - if (table_ndx >= size()) - throw LogicError(LogicError::table_index_out_of_range); - return m_table_names.get(table_ndx); -} - -inline bool Group::has_table(StringData name) const noexcept -{ - size_t ndx = find_table(name); - return ndx != not_found; -} - -inline size_t Group::find_table(StringData name) const noexcept -{ - if (!is_attached()) - return 0; - if (m_table_names.is_attached()) - return m_table_names.find_first(name); - return not_found; -} - -inline TableRef Group::get_table(size_t table_ndx) -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - Table* table = do_get_table(table_ndx, desc_matcher); // Throws - return TableRef(table); -} - -inline ConstTableRef Group::get_table(size_t table_ndx) const -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - const Table* table = do_get_table(table_ndx, desc_matcher); // Throws - return ConstTableRef(table); -} - -inline TableRef Group::get_table(StringData name) -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - Table* table = do_get_table(name, desc_matcher); // Throws - return TableRef(table); -} - -inline ConstTableRef Group::get_table(StringData name) const -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - const Table* table = do_get_table(name, desc_matcher); // Throws - return ConstTableRef(table); -} - -inline TableRef Group::insert_table(size_t table_ndx, StringData name, bool require_unique_name) -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescSetter desc_setter = nullptr; // Do not add any columns - Table* table = do_insert_table(table_ndx, name, desc_setter, require_unique_name); // Throws - return TableRef(table); -} - -inline TableRef Group::add_table(StringData name, bool require_unique_name) -{ - return insert_table(size(), name, require_unique_name); -} - -inline TableRef Group::get_or_insert_table(size_t table_ndx, StringData name, bool* was_added) -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - DescSetter desc_setter = nullptr; // Do not add any columns - Table* table = do_get_or_insert_table(table_ndx, name, desc_matcher, desc_setter, was_added); // Throws - return TableRef(table); -} - -inline TableRef Group::get_or_add_table(StringData name, bool* was_added) -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = nullptr; // Do not check descriptor - DescSetter desc_setter = nullptr; // Do not add any columns - Table* table = do_get_or_add_table(name, desc_matcher, desc_setter, was_added); // Throws - return TableRef(table); -} - -template -inline BasicTableRef Group::get_table(size_t table_ndx) -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - Table* table = do_get_table(table_ndx, desc_matcher); // Throws - return BasicTableRef(static_cast(table)); -} - -template -inline BasicTableRef Group::get_table(size_t table_ndx) const -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - const Table* table = do_get_table(table_ndx, desc_matcher); // Throws - return BasicTableRef(static_cast(table)); -} - -template -inline BasicTableRef Group::get_table(StringData name) -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - Table* table = do_get_table(name, desc_matcher); // Throws - return BasicTableRef(static_cast(table)); -} - -template -inline BasicTableRef Group::get_table(StringData name) const -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - const Table* table = do_get_table(name, desc_matcher); // Throws - return BasicTableRef(static_cast(table)); -} - -template -inline BasicTableRef Group::insert_table(size_t table_ndx, StringData name, bool require_unique_name) -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescSetter desc_setter = &T::set_dynamic_type; - Table* table = do_insert_table(table_ndx, name, desc_setter, require_unique_name); // Throws - return BasicTableRef(static_cast(table)); -} - -template -inline BasicTableRef Group::add_table(StringData name, bool require_unique_name) -{ - return insert_table(size(), name, require_unique_name); -} - -template -BasicTableRef Group::get_or_insert_table(size_t table_ndx, StringData name, bool* was_added) -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - DescSetter desc_setter = &T::set_dynamic_type; - Table* table = do_get_or_insert_table(table_ndx, name, desc_matcher, desc_setter, was_added); // Throws - return BasicTableRef(static_cast(table)); -} - -template -BasicTableRef Group::get_or_add_table(StringData name, bool* was_added) -{ - static_assert(IsBasicTable::value, "Invalid table type"); - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - DescMatcher desc_matcher = &T::matches_dynamic_type; - DescSetter desc_setter = &T::set_dynamic_type; - Table* table = do_get_or_add_table(name, desc_matcher, desc_setter, was_added); // Throws - return BasicTableRef(static_cast(table)); -} - -template -void Group::to_json(S& out, size_t link_depth, std::map* renames) const -{ - if (!is_attached()) - throw LogicError(LogicError::detached_accessor); - - std::map renames2; - renames = renames ? renames : &renames2; - - out << "{"; - - for (size_t i = 0; i < m_tables.size(); ++i) { - StringData name = m_table_names.get(i); - std::map& m = *renames; - if (m[name] != "") - name = m[name]; - - ConstTableRef table = get_table(i); - - if (i) - out << ","; - out << "\"" << name << "\""; - out << ":"; - table->to_json(out, link_depth, renames); - } - - out << "}"; -} - -inline void Group::init_array_parents() noexcept -{ - m_table_names.set_parent(&m_top, 0); - m_tables.set_parent(&m_top, 1); -} - -inline void Group::update_child_ref(size_t child_ndx, ref_type new_ref) -{ - m_tables.set(child_ndx, new_ref); -} - -inline ref_type Group::get_child_ref(size_t child_ndx) const noexcept -{ - return m_tables.get_as_ref(child_ndx); -} - -inline StringData Group::get_child_name(size_t child_ndx) const noexcept -{ - return m_table_names.get(child_ndx); -} - -inline void Group::child_accessor_destroyed(Table*) noexcept -{ - // Ignore -} - -inline bool Group::has_cascade_notification_handler() const noexcept -{ - return !!m_notify_handler; -} - -inline void -Group::set_cascade_notification_handler(std::function new_handler) noexcept -{ - m_notify_handler = std::move(new_handler); -} - -inline void Group::send_cascade_notification(const CascadeNotification& notification) const -{ - if (m_notify_handler) - m_notify_handler(notification); -} - -inline bool Group::has_schema_change_notification_handler() const noexcept -{ - return !!m_schema_change_handler; -} - -inline void Group::set_schema_change_notification_handler(std::function new_handler) noexcept -{ - m_schema_change_handler = std::move(new_handler); -} - -inline void Group::send_schema_change_notification() const -{ - if (m_schema_change_handler) - m_schema_change_handler(); -} - -inline void Group::get_version_and_history_type(const Array& top, _impl::History::version_type& version, - int& history_type) noexcept -{ - _impl::History::version_type version_2 = 0; - int history_type_2 = 0; - if (top.is_attached()) { - if (top.size() >= 6) { - REALM_ASSERT(top.size() >= 7); - version_2 = _impl::History::version_type(top.get(6) / 2); - } - if (top.size() >= 8) { - REALM_ASSERT(top.size() >= 9); - history_type_2 = int(top.get(7) / 2); - } - } - // Version 0 is not a legal initial version, so it has to be set to 1 - // instead. - if (version_2 == 0) - version_2 = 1; - version = version_2; - history_type = history_type_2; -} - -inline ref_type Group::get_history_ref(const Array& top) noexcept -{ - if (top.is_attached()) { - if (top.size() >= 8) { - REALM_ASSERT(top.size() >= 9); - return top.get_as_ref(8); - } - } - return 0; -} - -inline void Group::set_history_parent(Array& history_root) noexcept -{ - history_root.set_parent(&m_top, 8); -} - -inline void Group::prepare_history_parent(Array& history_root, int history_type) -{ - REALM_ASSERT(m_alloc.get_file_format_version() >= 4); - // Ensure that there are slots for both the history type and the history - // ref. - while (m_top.size() < 9) - m_top.add(0); // Throws - m_top.set(7, RefOrTagged::make_tagged(history_type)); // Throws - set_history_parent(history_root); -} - -class Group::TableWriter { -public: - virtual ref_type write_names(_impl::OutputStream&) = 0; - virtual ref_type write_tables(_impl::OutputStream&) = 0; - virtual ~TableWriter() noexcept - { - } -}; - -inline const Table* Group::do_get_table(size_t table_ndx, DescMatcher desc_matcher) const -{ - return const_cast(this)->do_get_table(table_ndx, desc_matcher); // Throws -} - -inline const Table* Group::do_get_table(StringData name, DescMatcher desc_matcher) const -{ - return const_cast(this)->do_get_table(name, desc_matcher); // Throws -} - -inline void Group::reset_free_space_tracking() -{ - m_alloc.reset_free_space_tracking(); // Throws -} - -inline Replication* Group::get_replication() const noexcept -{ - return m_alloc.get_replication(); -} - -inline void Group::set_replication(Replication* repl) noexcept -{ - m_alloc.set_replication(repl); -} - -// The purpose of this class is to give internal access to some, but -// not all of the non-public parts of the Group class. -class _impl::GroupFriend { -public: - static Allocator& get_alloc(Group& group) noexcept - { - return group.m_alloc; - } - - static Table& get_table(Group& group, size_t ndx_in_group) - { - Group::DescMatcher desc_matcher = 0; // Do not check descriptor - Table* table = group.do_get_table(ndx_in_group, desc_matcher); // Throws - return *table; - } - - static const Table& get_table(const Group& group, size_t ndx_in_group) - { - Group::DescMatcher desc_matcher = 0; // Do not check descriptor - const Table* table = group.do_get_table(ndx_in_group, desc_matcher); // Throws - return *table; - } - - static Table* get_table(Group& group, StringData name) - { - Group::DescMatcher desc_matcher = 0; // Do not check descriptor - Table* table = group.do_get_table(name, desc_matcher); // Throws - return table; - } - - static const Table* get_table(const Group& group, StringData name) - { - Group::DescMatcher desc_matcher = 0; // Do not check descriptor - const Table* table = group.do_get_table(name, desc_matcher); // Throws - return table; - } - - static Table& insert_table(Group& group, size_t table_ndx, StringData name, bool require_unique_name) - { - Group::DescSetter desc_setter = nullptr; // Do not add any columns - return *group.do_insert_table(table_ndx, name, desc_setter, require_unique_name); - } - - static Table& add_table(Group& group, StringData name, bool require_unique_name) - { - return insert_table(group, group.size(), name, require_unique_name); - } - - static Table& get_or_insert_table(Group& group, size_t table_ndx, StringData name, bool* was_inserted) - { - Group::DescMatcher desc_matcher = nullptr; // Do not check descriptor - Group::DescSetter desc_setter = nullptr; // Do not add any columns - return *group.do_get_or_insert_table(table_ndx, name, desc_matcher, desc_setter, was_inserted); - } - - static Table& get_or_add_table(Group& group, StringData name, bool* was_inserted) - { - Group::DescMatcher desc_matcher = nullptr; // Do not check descriptor - Group::DescSetter desc_setter = nullptr; // Do not add any columns - return *group.do_get_or_add_table(name, desc_matcher, desc_setter, was_inserted); - } - - static void send_cascade_notification(const Group& group, const Group::CascadeNotification& notification) - { - group.send_cascade_notification(notification); - } - - static Replication* get_replication(const Group& group) noexcept - { - return group.get_replication(); - } - - static void set_replication(Group& group, Replication* repl) noexcept - { - group.set_replication(repl); - } - - static void detach(Group& group) noexcept - { - group.detach(); - } - - static void attach_shared(Group& group, ref_type new_top_ref, size_t new_file_size, bool writable) - { - group.attach_shared(new_top_ref, new_file_size, writable); // Throws - } - - static void reset_free_space_tracking(Group& group) - { - group.reset_free_space_tracking(); // Throws - } - - static void remap(Group& group, size_t new_file_size) - { - group.remap(new_file_size); // Throws - } - - static void remap_and_update_refs(Group& group, ref_type new_top_ref, size_t new_file_size) - { - group.remap_and_update_refs(new_top_ref, new_file_size); // Throws - } - - static void advance_transact(Group& group, ref_type new_top_ref, size_t new_file_size, - _impl::NoCopyInputStream& in) - { - group.advance_transact(new_top_ref, new_file_size, in); // Throws - } - - static void create_empty_group_when_missing(Group& group) - { - if (!group.m_top.is_attached()) - group.create_empty_group(); // Throws - } - - static void get_version_and_history_type(Allocator& alloc, ref_type top_ref, - _impl::History::version_type& version, int& history_type) noexcept - { - Array top(alloc); - if (top_ref != 0) - top.init_from_ref(top_ref); - Group::get_version_and_history_type(top, version, history_type); - } - - static ref_type get_history_ref(const Group& group) noexcept - { - return Group::get_history_ref(group.m_top); - } - - static ref_type get_history_ref(Allocator& alloc, ref_type top_ref) noexcept - { - Array top(alloc); - if (top_ref != 0) - top.init_from_ref(top_ref); - return Group::get_history_ref(top); - } - - static void set_history_parent(Group& group, Array& history_root) noexcept - { - group.set_history_parent(history_root); - } - - static void prepare_history_parent(Group& group, Array& history_root, int history_type) - { - group.prepare_history_parent(history_root, history_type); // Throws - } - - static int get_file_format_version(const Group& group) noexcept - { - return group.get_file_format_version(); - } - - static void set_file_format_version(Group& group, int file_format_version) noexcept - { - group.set_file_format_version(file_format_version); - } - - static int get_committed_file_format_version(const Group& group) noexcept - { - return group.get_committed_file_format_version(); - } - - static int get_target_file_format_version_for_session(int current_file_format_version, int history_type) noexcept - { - return Group::get_target_file_format_version_for_session(current_file_format_version, history_type); - } - - static void upgrade_file_format(Group& group, int target_file_format_version) - { - group.upgrade_file_format(target_file_format_version); // Throws - } -}; - - -struct CascadeState : Group::CascadeNotification { - /// If non-null, then no recursion will be performed for rows of that - /// table. The effect is then exactly as if all the rows of that table were - /// added to \a state.rows initially, and then removed again after the - /// explicit invocations of Table::cascade_break_backlinks_to() (one for - /// each initiating row). This is used by Table::clear() to avoid - /// reentrance. - /// - /// Must never be set concurrently with stop_on_link_list_column. - Table* stop_on_table = nullptr; - - /// If non-null, then Table::cascade_break_backlinks_to() will skip the - /// removal of reciprocal backlinks for the link list at - /// stop_on_link_list_row_ndx in this column, and no recursion will happen - /// on its behalf. This is used by LinkView::clear() to avoid reentrance. - /// - /// Must never be set concurrently with stop_on_table. - LinkListColumn* stop_on_link_list_column = nullptr; - - /// Is ignored if stop_on_link_list_column is null. - size_t stop_on_link_list_row_ndx = 0; - - /// If false, the links field is not needed, so any work done just for that - /// can be skipped. - bool track_link_nullifications = false; -}; - -inline bool Group::CascadeNotification::row::operator==(const row& r) const noexcept -{ - return table_ndx == r.table_ndx && row_ndx == r.row_ndx; -} - -inline bool Group::CascadeNotification::row::operator!=(const row& r) const noexcept -{ - return !(*this == r); -} - -inline bool Group::CascadeNotification::row::operator<(const row& r) const noexcept -{ - return table_ndx < r.table_ndx || (table_ndx == r.table_ndx && row_ndx < r.row_ndx); -} - -} // namespace realm - -#endif // REALM_GROUP_HPP diff --git a/Example/Pods/Realm/include/core/realm/group_shared.hpp b/Example/Pods/Realm/include/core/realm/group_shared.hpp deleted file mode 100644 index 6b36b97..0000000 --- a/Example/Pods/Realm/include/core/realm/group_shared.hpp +++ /dev/null @@ -1,1160 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_GROUP_SHARED_HPP -#define REALM_GROUP_SHARED_HPP - -#ifdef REALM_DEBUG -#include // usleep() -#endif - -#include -#include -#include -#include -#ifndef _WIN32 -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - -namespace _impl { -class SharedGroupFriend; -class WriteLogCollector; -} - -/// Thrown by SharedGroup::open() if the lock file is already open in another -/// process which can't share mutexes with this process -struct IncompatibleLockFile : std::runtime_error { - IncompatibleLockFile(const std::string& msg) - : std::runtime_error("Incompatible lock file. " + msg) - { - } -}; - - -/// A SharedGroup facilitates transactions. -/// -/// When multiple threads or processes need to access a database -/// concurrently, they must do so using transactions. By design, -/// Realm does not allow for multiple threads (or processes) to -/// share a single instance of SharedGroup. Instead, each concurrently -/// executing thread or process must use a separate instance of -/// SharedGroup. -/// -/// Each instance of SharedGroup manages a single transaction at a -/// time. That transaction can be either a read transaction, or a -/// write transaction. -/// -/// Utility classes ReadTransaction and WriteTransaction are provided -/// to make it safe and easy to work with transactions in a scoped -/// manner (by means of the RAII idiom). However, transactions can -/// also be explicitly started (begin_read(), begin_write()) and -/// stopped (end_read(), commit(), rollback()). -/// -/// If a transaction is active when the SharedGroup is destroyed, that -/// transaction is implicitly terminated, either by a call to -/// end_read() or rollback(). -/// -/// Two processes that want to share a database file must reside on -/// the same host. -/// -/// -/// Desired exception behavior (not yet fully implemented) -/// ------------------------------------------------------ -/// -/// - If any data access API function throws an unexpected exception during a -/// read transaction, the shared group accessor is left in state "error -/// during read". -/// -/// - If any data access API function throws an unexpected exception during a -/// write transaction, the shared group accessor is left in state "error -/// during write". -/// -/// - If SharedGroup::begin_write() or SharedGroup::begin_read() throws an -/// unexpected exception, the shared group accessor is left in state "no -/// transaction in progress". -/// -/// - SharedGroup::end_read() and SharedGroup::rollback() do not throw. -/// -/// - If SharedGroup::commit() throws an unexpected exception, the shared group -/// accessor is left in state "error during write" and the transaction was -/// not committed. -/// -/// - If SharedGroup::advance_read() or SharedGroup::promote_to_write() throws -/// an unexpected exception, the shared group accessor is left in state -/// "error during read". -/// -/// - If SharedGroup::commit_and_continue_as_read() or -/// SharedGroup::rollback_and_continue_as_read() throws an unexpected -/// exception, the shared group accessor is left in state "error during -/// write". -/// -/// It has not yet been decided exactly what an "unexpected exception" is, but -/// `std::bad_alloc` is surely one example. On the other hand, an expected -/// exception is one that is mentioned in the function specific documentation, -/// and is used to abort an operation due to a special, but expected condition. -/// -/// States -/// ------ -/// -/// - A newly created shared group accessor is in state "no transaction in -/// progress". -/// -/// - In state "error during read", almost all Realm API functions are -/// illegal on the connected group of accessors. The only valid operations -/// are destruction of the shared group, and SharedGroup::end_read(). If -/// SharedGroup::end_read() is called, the new state becomes "no transaction -/// in progress". -/// -/// - In state "error during write", almost all Realm API functions are -/// illegal on the connected group of accessors. The only valid operations -/// are destruction of the shared group, and SharedGroup::rollback(). If -/// SharedGroup::end_write() is called, the new state becomes "no transaction -/// in progress" -class SharedGroup { -public: - /// \brief Same as calling the corresponding version of open() on a instance - /// constructed in the unattached state. Exception safety note: if the - /// `upgrade_callback` throws, then the file will be closed properly and the - /// upgrade will be aborted. - explicit SharedGroup(const std::string& file, bool no_create = false, - const SharedGroupOptions options = SharedGroupOptions()); - - /// \brief Same as calling the corresponding version of open() on a instance - /// constructed in the unattached state. Exception safety note: if the - /// `upgrade_callback` throws, then the file will be closed properly and - /// the upgrade will be aborted. - explicit SharedGroup(Replication& repl, const SharedGroupOptions options = SharedGroupOptions()); - - struct unattached_tag { - }; - - /// Create a SharedGroup instance in its unattached state. It may - /// then be attached to a database file later by calling - /// open(). You may test whether this instance is currently in its - /// attached state by calling is_attached(). Calling any other - /// function (except the destructor) while in the unattached state - /// has undefined behavior. - SharedGroup(unattached_tag) noexcept; - - ~SharedGroup() noexcept; - - /// Attach this SharedGroup instance to the specified database file. - /// - /// While at least one instance of SharedGroup exists for a specific - /// database file, a "lock" file will be present too. The lock file will be - /// placed in the same directory as the database file, and its name will be - /// derived by appending ".lock" to the name of the database file. - /// - /// When multiple SharedGroup instances refer to the same file, they must - /// specify the same durability level, otherwise an exception will be - /// thrown. - /// - /// \param file Filesystem path to a Realm database file. - /// - /// \param no_create If the database file does not already exist, it will be - /// created (unless this is set to true.) When multiple threads are involved, - /// it is safe to let the first thread, that gets to it, create the file. - /// - /// \param options See SharedGroupOptions for details of each option. - /// Sensible defaults are provided if this parameter is left out. - /// - /// Calling open() on a SharedGroup instance that is already in the attached - /// state has undefined behavior. - /// - /// \throw util::File::AccessError If the file could not be opened. If the - /// reason corresponds to one of the exception types that are derived from - /// util::File::AccessError, the derived exception type is thrown. Note that - /// InvalidDatabase is among these derived exception types. - /// - /// \throw FileFormatUpgradeRequired only if \a SharedGroupOptions::allow_upgrade - /// is `false` and an upgrade is required. - void open(const std::string& file, bool no_create = false, - const SharedGroupOptions options = SharedGroupOptions()); - - /// Open this group in replication mode. The specified Replication instance - /// must remain in existence for as long as the SharedGroup. - void open(Replication&, const SharedGroupOptions options = SharedGroupOptions()); - - /// Close any open database, returning to the unattached state. - void close() noexcept; - - /// A SharedGroup may be created in the unattached state, and then - /// later attached to a file with a call to open(). Calling any - /// function other than open(), is_attached(), and ~SharedGroup() - /// on an unattached instance results in undefined behavior. - bool is_attached() const noexcept; - - /// Reserve disk space now to avoid allocation errors at a later - /// point in time, and to minimize on-disk fragmentation. In some - /// cases, less fragmentation translates into improved - /// performance. - /// - /// When supported by the system, a call to this function will - /// make the database file at least as big as the specified size, - /// and cause space on the target device to be allocated (note - /// that on many systems on-disk allocation is done lazily by - /// default). If the file is already bigger than the specified - /// size, the size will be unchanged, and on-disk allocation will - /// occur only for the initial section that corresponds to the - /// specified size. On systems that do not support preallocation, - /// this function has no effect. To know whether preallocation is - /// supported by Realm on your platform, call - /// util::File::is_prealloc_supported(). - /// - /// It is an error to call this function on an unattached shared - /// group. Doing so will result in undefined behavior. - void reserve(size_t size_in_bytes); - - /// Querying for changes: - /// - /// NOTE: - /// "changed" means that one or more commits has been made to the database - /// since the SharedGroup (on which wait_for_change() is called) last - /// started, committed, promoted or advanced a transaction. If the - /// SharedGroup has not yet begun a transaction, "changed" is undefined. - /// - /// No distinction is made between changes done by another process - /// and changes done by another thread in the same process as the caller. - /// - /// Has db been changed ? - bool has_changed(); - - /// The calling thread goes to sleep until the database is changed, or - /// until wait_for_change_release() is called. After a call to - /// wait_for_change_release() further calls to wait_for_change() will return - /// immediately. To restore the ability to wait for a change, a call to - /// enable_wait_for_change() is required. Return true if the database has - /// changed, false if it might have. - bool wait_for_change(); - - /// release any thread waiting in wait_for_change() on *this* SharedGroup. - void wait_for_change_release(); - - /// re-enable waiting for change - void enable_wait_for_change(); - // Transactions: - - using version_type = _impl::History::version_type; - using VersionID = realm::VersionID; - - /// Thrown by begin_read() if the specified version does not correspond to a - /// bound (or tethered) snapshot. - struct BadVersion; - - /// \defgroup group_shared_transactions - //@{ - - /// begin_read() initiates a new read transaction. A read transaction is - /// bound to, and provides access to a particular snapshot of the underlying - /// Realm (in general the latest snapshot, but see \a version). It cannot be - /// used to modify the Realm, and in that sense, a read transaction is not a - /// real transaction. - /// - /// begin_write() initiates a new write transaction. A write transaction - /// allows the application to both read and modify the underlying Realm - /// file. At most one write transaction can be in progress at any given time - /// for a particular underlying Realm file. If another write transaction is - /// already in progress, begin_write() will block the caller until the other - /// write transaction terminates. No guarantees are made about the order in - /// which multiple concurrent requests will be served. - /// - /// It is an error to call begin_read() or begin_write() on a SharedGroup - /// object with an active read or write transaction. - /// - /// If begin_read() or begin_write() throws, no transaction is initiated, - /// and the application may try to initiate a new read or write transaction - /// later. - /// - /// end_read() terminates the active read transaction. If no read - /// transaction is active, end_read() does nothing. It is an error to call - /// this function on a SharedGroup object with an active write - /// transaction. end_read() does not throw. - /// - /// commit() commits all changes performed in the context of the active - /// write transaction, and thereby terminates that transaction. This - /// produces a new snapshot in the underlying Realm. commit() returns the - /// version associated with the new snapshot. It is an error to call - /// commit() when there is no active write transaction. If commit() throws, - /// no changes will have been committed, and the transaction will still be - /// active, but in a bad state. In that case, the application must either - /// call rollback() to terminate the bad transaction (in which case a new - /// transaction can be initiated), call close() which also terminates the - /// bad transaction, or destroy the SharedGroup object entirely. When the - /// transaction is in a bad state, the application is not allowed to call - /// any method on the Group accessor or on any of its subordinate accessors - /// (Table, Row, Descriptor). Note that the transaction is also left in a - /// bad state when a modifying operation on any subordinate accessor throws. - /// - /// rollback() terminates the active write transaction and discards any - /// changes performed in the context of it. If no write transaction is - /// active, rollback() does nothing. It is an error to call this function in - /// a SharedGroup object with an active read transaction. rollback() does - /// not throw. - /// - /// the Group accessor and all subordinate accessors (Table, Row, - /// Descriptor) that are obtained in the context of a particular read or - /// write transaction will become detached upon termination of that - /// transaction, which means that they can no longer be used to access the - /// underlying objects. - /// - /// Subordinate accessors that were detached at the end of the previous - /// read or write transaction will not be automatically reattached when a - /// new transaction is initiated. The application must reobtain new - /// accessors during a new transaction to regain access to the underlying - /// objects. - /// - /// \param version If specified, this must be the version associated with a - /// *bound* snapshot. A snapshot is said to be bound (or tethered) if there - /// is at least one active read or write transaction bound to it. A read - /// transaction is bound to the snapshot that it provides access to. A write - /// transaction is bound to the latest snapshot available at the time of - /// initiation of the write transaction. If the specified version is not - /// associated with a bound snapshot, this function throws BadVersion. - /// - /// \throw BadVersion Thrown by begin_read() if the specified version does - /// not correspond to a bound (or tethered) snapshot. - - const Group& begin_read(VersionID version = VersionID()); - void end_read() noexcept; - Group& begin_write(); - version_type commit(); - void rollback() noexcept; - - //@} - - enum TransactStage { - transact_Ready, - transact_Reading, - transact_Writing, - }; - - /// Get the current transaction type - TransactStage get_transact_stage() const noexcept; - - /// Get a version id which may be used to request a different SharedGroup - /// to start transaction at a specific version. - VersionID get_version_of_current_transaction(); - - /// Report the number of distinct versions currently stored in the database. - /// Note: the database only cleans up versions as part of commit, so ending - /// a read transaction will not immediately release any versions. - uint_fast64_t get_number_of_versions(); - - /// Compact the database file. - /// - The method will throw if called inside a transaction. - /// - The method will throw if called in unattached state. - /// - The method will return false if other SharedGroups are accessing the - /// database in which case compaction is not done. This is not - /// necessarily an error. - /// It will return true following successful compaction. - /// While compaction is in progress, attempts by other - /// threads or processes to open the database will wait. - /// Be warned that resource requirements for compaction is proportional to - /// the amount of live data in the database. - /// Compaction works by writing the database contents to a temporary - /// database file and then replacing the database with the temporary one. - /// The name of the temporary file is formed by appending - /// ".tmp_compaction_space" to the name of the database - /// - /// FIXME: This function is not yet implemented in an exception-safe manner, - /// therefore, if it throws, the application should not attempt to - /// continue. If may not even be safe to destroy the SharedGroup object. - /// - /// WARNING / FIXME: compact() should NOT be exposed publicly on Windows - /// because it's not crash safe! It may corrupt your database if something fails - bool compact(); - -#ifdef REALM_DEBUG - void test_ringbuf(); -#endif - - /// To handover a table view, query, linkview or row accessor of type T, you - /// must wrap it into a Handover for the transfer. Wrapping and - /// unwrapping of a handover object is done by the methods - /// 'export_for_handover()' and 'import_from_handover()' declared below. - /// 'export_for_handover()' returns a Handover object, and - /// 'import_for_handover()' consumes that object, producing a new accessor - /// which is ready for use in the context of the importing SharedGroup. - /// - /// The Handover always creates a new accessor object at the importing side. - /// For TableViews, there are 3 forms of handover. - /// - /// - with payload move: the payload is handed over and ends up as a payload - /// held by the accessor at the importing side. The accessor on the - /// exporting side will rerun its query and generate a new payload, if - /// TableView::sync_if_needed() is called. If the original payload was in - /// sync at the exporting side, it will also be in sync at the importing - /// side. This is indicated to handover_export() by the argument - /// MutableSourcePayload::Move - /// - /// - with payload copy: a copy of the payload is handed over, so both the - /// accessors on the exporting side *and* the accessors created at the - /// importing side has their own payload. This is indicated to - /// handover_export() by the argument ConstSourcePayload::Copy - /// - /// - without payload: the payload stays with the accessor on the exporting - /// side. On the importing side, the new accessor is created without - /// payload. A call to TableView::sync_if_needed() will trigger generation - /// of a new payload. This form of handover is indicated to - /// handover_export() by the argument ConstSourcePayload::Stay. - /// - /// For all other (non-TableView) accessors, handover is done with payload - /// copy, since the payload is trivial. - /// - /// Handover *without* payload is useful when you want to ship a tableview - /// with its query for execution in a background thread. Handover with - /// *payload move* is useful when you want to transfer the result back. - /// - /// Handover *without* payload or with payload copy is guaranteed *not* to - /// change the accessors on the exporting side. - /// - /// Handover is *not* thread safe and should be carried out - /// by the thread that "owns" the involved accessors. - /// - /// Handover is transitive: - /// If the object being handed over depends on other views - /// (table- or link- ), those objects will be handed over as well. The mode - /// of handover (payload copy, payload move, without payload) is applied - /// recursively. Note: If you are handing over a tableview dependent upon - /// another tableview and using MutableSourcePayload::Move, - /// you are on thin ice! - /// - /// On the importing side, the top-level accessor being created during - /// import takes ownership of all other accessors (if any) being created as - /// part of the import. - - /// Type used to support handover of accessors between shared groups. - template - struct Handover; - - /// thread-safe/const export (mode is Stay or Copy) - /// during export, the following operations on the shared group is locked: - /// - advance_read(), promote_to_write(), commit_and_continue_as_read(), - /// rollback_and_continue_as_read(), close() - template - std::unique_ptr> export_for_handover(const T& accessor, ConstSourcePayload mode); - - // specialization for handover of Rows - template - std::unique_ptr>> export_for_handover(const BasicRow& accessor); - - // destructive export (mode is Move) - template - std::unique_ptr> export_for_handover(T& accessor, MutableSourcePayload mode); - - /// Import an accessor wrapped in a handover object. The import will fail - /// if the importing SharedGroup is viewing a version of the database that - /// is different from the exporting SharedGroup. The call to - /// import_from_handover is not thread-safe. - template - std::unique_ptr import_from_handover(std::unique_ptr> handover); - - // We need two cases for handling of LinkViews, because they are ref counted. - std::unique_ptr> export_linkview_for_handover(const LinkViewRef& accessor); - LinkViewRef import_linkview_from_handover(std::unique_ptr> handover); - - // likewise for Tables. - std::unique_ptr> export_table_for_handover(const TableRef& accessor); - TableRef import_table_from_handover(std::unique_ptr> handover); - - /// When doing handover to background tasks that may be run later, we - /// may want to momentarily pin the current version until the other thread - /// has retrieved it. - /// - /// Pinning can be done in both read- and write-transactions, but with different - /// semantics. When pinning during a read-transaction, the version pinned is the - /// one accessible during the read-transaction. When pinning during a write-transaction, - /// the version pinned will be the last version that was succesfully committed to the - /// realm file at the point in time, when the write-transaction was started. - /// - /// The release is not thread-safe, so it has to be done on the SharedGroup - /// associated with the thread calling unpin_version(), and the SharedGroup - /// must be attached to the realm file at the point of unpinning. - - // Pin version for handover (not thread safe) - VersionID pin_version(); - - // Release pinned version (not thread safe) - void unpin_version(VersionID version); - -private: - struct SharedInfo; - struct ReadCount; - struct ReadLockInfo { - uint_fast64_t m_version = std::numeric_limits::max(); - uint_fast32_t m_reader_idx = 0; - ref_type m_top_ref = 0; - size_t m_file_size = 0; - }; - class ReadLockUnlockGuard; - - // Member variables - Group m_group; - ReadLockInfo m_read_lock; - uint_fast32_t m_local_max_entry; - util::File m_file; - util::File::Map m_file_map; // Never remapped - util::File::Map m_reader_map; - bool m_wait_for_change_enabled; - std::string m_lockfile_path; - std::string m_lockfile_prefix; - std::string m_db_path; - std::string m_coordination_dir; - const char* m_key; - TransactStage m_transact_stage; - util::InterprocessMutex m_writemutex; -#ifdef REALM_ASYNC_DAEMON - util::InterprocessMutex m_balancemutex; -#endif - util::InterprocessMutex m_controlmutex; -#ifndef _WIN32 -#ifdef REALM_ASYNC_DAEMON - util::InterprocessCondVar m_room_to_write; - util::InterprocessCondVar m_work_to_do; - util::InterprocessCondVar m_daemon_becomes_ready; -#endif - util::InterprocessCondVar m_new_commit_available; -#endif - std::function m_upgrade_callback; - - void do_open(const std::string& file, bool no_create, bool is_backend, const SharedGroupOptions options); - - // Ring buffer management - bool ringbuf_is_empty() const noexcept; - size_t ringbuf_size() const noexcept; - size_t ringbuf_capacity() const noexcept; - bool ringbuf_is_first(size_t ndx) const noexcept; - void ringbuf_remove_first() noexcept; - size_t ringbuf_find(uint64_t version) const noexcept; - ReadCount& ringbuf_get(size_t ndx) noexcept; - ReadCount& ringbuf_get_first() noexcept; - ReadCount& ringbuf_get_last() noexcept; - void ringbuf_put(const ReadCount& v); - void ringbuf_expand(); - - /// Grab a read lock on the snapshot associated with the specified - /// version. If `version_id == VersionID()`, a read lock will be grabbed on - /// the latest available snapshot. Fails if the snapshot is no longer - /// available. - /// - /// As a side effect update memory mapping to ensure that the ringbuffer - /// entries referenced in the readlock info is accessible. - /// - /// FIXME: It needs to be made more clear exactly under which conditions - /// this function fails. Also, why is it useful to promise anything about - /// detection of bad versions? Can we really promise enough to make such a - /// promise useful to the caller? - void grab_read_lock(ReadLockInfo&, VersionID); - - // Release a specific read lock. The read lock MUST have been obtained by a - // call to grab_read_lock(). - void release_read_lock(ReadLockInfo&) noexcept; - - void do_begin_read(VersionID, bool writable); - void do_end_read() noexcept; - void do_begin_write(); - version_type do_commit(); - void do_end_write() noexcept; - - /// Returns the version of the latest snapshot. - version_type get_version_of_latest_snapshot(); - - /// Returns the version of the snapshot bound in the current read or write - /// transaction. It is an error to call this function when no transaction is - /// in progress. - version_type get_version_of_bound_snapshot() const noexcept; - - // make sure the given index is within the currently mapped area. - // if not, expand the mapped area. Returns true if the area is expanded. - bool grow_reader_mapping(uint_fast32_t index); - - // Must be called only by someone that has a lock on the write - // mutex. - void low_level_commit(uint_fast64_t new_version); - - void do_async_commits(); - - void upgrade_file_format(bool allow_file_format_upgrade, int target_file_format_version); - - //@{ - /// See LangBindHelper. - template - void advance_read(O* observer, VersionID); - template - void promote_to_write(O* observer); - version_type commit_and_continue_as_read(); - template - void rollback_and_continue_as_read(O* observer); - //@} - - /// Returns true if, and only if _impl::History::update_early_from_top_ref() - /// was called during the execution of this function. - template - bool do_advance_read(O* observer, VersionID, _impl::History&); - - /// If there is an associated \ref Replication object, then this function - /// returns `repl->get_history()` where `repl` is that Replication object, - /// otherwise this function returns null. - _impl::History* get_history(); - - int get_file_format_version() const noexcept; - - friend class _impl::SharedGroupFriend; -}; - - -class ReadTransaction { -public: - ReadTransaction(SharedGroup& sg) - : m_shared_group(sg) - { - m_shared_group.begin_read(); // Throws - } - - ~ReadTransaction() noexcept - { - m_shared_group.end_read(); - } - - bool has_table(StringData name) const noexcept - { - return get_group().has_table(name); - } - - ConstTableRef get_table(size_t table_ndx) const - { - return get_group().get_table(table_ndx); // Throws - } - - ConstTableRef get_table(StringData name) const - { - return get_group().get_table(name); // Throws - } - - template - BasicTableRef get_table(StringData name) const - { - return get_group().get_table(name); // Throws - } - - const Group& get_group() const noexcept; - - /// Get the version of the snapshot to which this read transaction is bound. - SharedGroup::version_type get_version() const noexcept; - -private: - SharedGroup& m_shared_group; -}; - - -class WriteTransaction { -public: - WriteTransaction(SharedGroup& sg) - : m_shared_group(&sg) - { - m_shared_group->begin_write(); // Throws - } - - ~WriteTransaction() noexcept - { - if (m_shared_group) - m_shared_group->rollback(); - } - - bool has_table(StringData name) const noexcept - { - return get_group().has_table(name); - } - - TableRef get_table(size_t table_ndx) const - { - return get_group().get_table(table_ndx); // Throws - } - - TableRef get_table(StringData name) const - { - return get_group().get_table(name); // Throws - } - - TableRef add_table(StringData name, bool require_unique_name = true) const - { - return get_group().add_table(name, require_unique_name); // Throws - } - - TableRef get_or_add_table(StringData name, bool* was_added = nullptr) const - { - return get_group().get_or_add_table(name, was_added); // Throws - } - - template - BasicTableRef get_table(StringData name) const - { - return get_group().get_table(name); // Throws - } - - template - BasicTableRef add_table(StringData name, bool require_unique_name = true) const - { - return get_group().add_table(name, require_unique_name); // Throws - } - - template - BasicTableRef get_or_add_table(StringData name, bool* was_added = nullptr) const - { - return get_group().get_or_add_table(name, was_added); // Throws - } - - Group& get_group() const noexcept; - - /// Get the version of the snapshot on which this write transaction is - /// based. - SharedGroup::version_type get_version() const noexcept; - - SharedGroup::version_type commit() - { - REALM_ASSERT(m_shared_group); - SharedGroup::version_type new_version = m_shared_group->commit(); - m_shared_group = nullptr; - return new_version; - } - - void rollback() noexcept - { - REALM_ASSERT(m_shared_group); - m_shared_group->rollback(); - m_shared_group = nullptr; - } - -private: - SharedGroup* m_shared_group; -}; - - -// Implementation: - -struct SharedGroup::BadVersion : std::exception { -}; - -inline SharedGroup::SharedGroup(const std::string& file, bool no_create, const SharedGroupOptions options) - : m_group(Group::shared_tag()) - , m_upgrade_callback(std::move(options.upgrade_callback)) -{ - open(file, no_create, options); // Throws -} - -inline SharedGroup::SharedGroup(unattached_tag) noexcept - : m_group(Group::shared_tag()) -{ -} - -inline SharedGroup::SharedGroup(Replication& repl, const SharedGroupOptions options) - : m_group(Group::shared_tag()) - , m_upgrade_callback(std::move(options.upgrade_callback)) -{ - open(repl, options); // Throws -} - -inline void SharedGroup::open(const std::string& path, bool no_create_file, const SharedGroupOptions options) -{ - // Exception safety: Since open() is called from constructors, if it throws, - // it must leave the file closed. - - bool is_backend = false; - do_open(path, no_create_file, is_backend, options); // Throws -} - -inline void SharedGroup::open(Replication& repl, const SharedGroupOptions options) -{ - // Exception safety: Since open() is called from constructors, if it throws, - // it must leave the file closed. - - REALM_ASSERT(!is_attached()); - - repl.initialize(*this); // Throws - - typedef _impl::GroupFriend gf; - gf::set_replication(m_group, &repl); - - std::string file = repl.get_database_path(); - bool no_create = false; - bool is_backend = false; - do_open(file, no_create, is_backend, options); // Throws -} - -inline bool SharedGroup::is_attached() const noexcept -{ - return m_file_map.is_attached(); -} - -inline SharedGroup::TransactStage SharedGroup::get_transact_stage() const noexcept -{ - return m_transact_stage; -} - -inline SharedGroup::version_type SharedGroup::get_version_of_bound_snapshot() const noexcept -{ - return m_read_lock.m_version; -} - -class SharedGroup::ReadLockUnlockGuard { -public: - ReadLockUnlockGuard(SharedGroup& shared_group, ReadLockInfo& read_lock) noexcept - : m_shared_group(shared_group) - , m_read_lock(&read_lock) - { - } - ~ReadLockUnlockGuard() noexcept - { - if (m_read_lock) - m_shared_group.release_read_lock(*m_read_lock); - } - void release() noexcept - { - m_read_lock = 0; - } - -private: - SharedGroup& m_shared_group; - ReadLockInfo* m_read_lock; -}; - - -template -struct SharedGroup::Handover { - std::unique_ptr patch; - std::unique_ptr clone; - VersionID version; -}; - -template -std::unique_ptr> SharedGroup::export_for_handover(const T& accessor, ConstSourcePayload mode) -{ - if (m_transact_stage != transact_Reading) - throw LogicError(LogicError::wrong_transact_state); - std::unique_ptr> result(new Handover()); - // Implementation note: - // often, the return value from clone will be T*, BUT it may be ptr to some - // base of T instead, so we must cast it to T*. This is always safe, because - // no matter the type, clone() will clone the actual accessor instance, and - // hence return an instance of the same type. - result->clone.reset(dynamic_cast(accessor.clone_for_handover(result->patch, mode).release())); - result->version = get_version_of_current_transaction(); - return move(result); -} - - -template -std::unique_ptr>> SharedGroup::export_for_handover(const BasicRow& accessor) -{ - if (m_transact_stage != transact_Reading) - throw LogicError(LogicError::wrong_transact_state); - std::unique_ptr>> result(new Handover>()); - // See implementation note above. - result->clone.reset(dynamic_cast*>(accessor.clone_for_handover(result->patch).release())); - result->version = get_version_of_current_transaction(); - return move(result); -} - - -template -std::unique_ptr> SharedGroup::export_for_handover(T& accessor, MutableSourcePayload mode) -{ - if (m_transact_stage != transact_Reading) - throw LogicError(LogicError::wrong_transact_state); - std::unique_ptr> result(new Handover()); - // see implementation note above. - result->clone.reset(dynamic_cast(accessor.clone_for_handover(result->patch, mode).release())); - result->version = get_version_of_current_transaction(); - return move(result); -} - - -template -std::unique_ptr SharedGroup::import_from_handover(std::unique_ptr> handover) -{ - if (handover->version != get_version_of_current_transaction()) { - throw BadVersion(); - } - std::unique_ptr result = move(handover->clone); - result->apply_and_consume_patch(handover->patch, m_group); - return result; -} - -template -inline void SharedGroup::advance_read(O* observer, VersionID version_id) -{ - if (m_transact_stage != transact_Reading) - throw LogicError(LogicError::wrong_transact_state); - - // It is an error if the new version precedes the currently bound one. - if (version_id.version < m_read_lock.m_version) - throw LogicError(LogicError::bad_version); - - _impl::History* hist = get_history(); // Throws - if (!hist) - throw LogicError(LogicError::no_history); - - do_advance_read(observer, version_id, *hist); // Throws -} - -template -inline void SharedGroup::promote_to_write(O* observer) -{ - if (m_transact_stage != transact_Reading) - throw LogicError(LogicError::wrong_transact_state); - - _impl::History* hist = get_history(); // Throws - if (!hist) - throw LogicError(LogicError::no_history); - - do_begin_write(); // Throws - try { - VersionID version = VersionID(); // Latest - bool history_updated = do_advance_read(observer, version, *hist); // Throws - - Replication* repl = m_group.get_replication(); - REALM_ASSERT(repl); // Presence of `repl` follows from the presence of `hist` - version_type current_version = m_read_lock.m_version; - repl->initiate_transact(current_version, history_updated); // Throws - - // If the group has no top array (top_ref == 0), create a new node - // structure for an empty group now, to be ready for modifications. See - // also Group::attach_shared(). - using gf = _impl::GroupFriend; - gf::create_empty_group_when_missing(m_group); // Throws - } - catch (...) { - do_end_write(); - throw; - } - - m_transact_stage = transact_Writing; -} - -template -inline void SharedGroup::rollback_and_continue_as_read(O* observer) -{ - if (m_transact_stage != transact_Writing) - throw LogicError(LogicError::wrong_transact_state); - - _impl::History* hist = get_history(); // Throws - if (!hist) - throw LogicError(LogicError::no_history); - - // Mark all managed space (beyond the attached file) as free. - using gf = _impl::GroupFriend; - gf::reset_free_space_tracking(m_group); // Throws - - BinaryData uncommitted_changes = hist->get_uncommitted_changes(); - - // FIXME: We are currently creating two transaction log parsers, one here, - // and one in advance_transact(). That is wasteful as the parser creation is - // expensive. - _impl::SimpleInputStream in(uncommitted_changes.data(), uncommitted_changes.size()); - _impl::TransactLogParser parser; // Throws - _impl::TransactReverser reverser; - parser.parse(in, reverser); // Throws - - if (observer && uncommitted_changes.size()) { - _impl::ReversedNoCopyInputStream reversed_in(reverser); - parser.parse(reversed_in, *observer); // Throws - observer->parse_complete(); // Throws - } - - ref_type top_ref = m_read_lock.m_top_ref; - size_t file_size = m_read_lock.m_file_size; - _impl::ReversedNoCopyInputStream reversed_in(reverser); - gf::advance_transact(m_group, top_ref, file_size, reversed_in); // Throws - - do_end_write(); - - Replication* repl = gf::get_replication(m_group); - REALM_ASSERT(repl); // Presence of `repl` follows from the presence of `hist` - repl->abort_transact(); - - m_transact_stage = transact_Reading; -} - -template -inline bool SharedGroup::do_advance_read(O* observer, VersionID version_id, _impl::History& hist) -{ - ReadLockInfo new_read_lock; - grab_read_lock(new_read_lock, version_id); // Throws - REALM_ASSERT(new_read_lock.m_version >= m_read_lock.m_version); - if (new_read_lock.m_version == m_read_lock.m_version) { - release_read_lock(new_read_lock); - // _impl::History::update_early_from_top_ref() was not called - return false; - } - - ReadLockUnlockGuard g(*this, new_read_lock); - { - version_type new_version = new_read_lock.m_version; - size_t new_file_size = new_read_lock.m_file_size; - ref_type new_top_ref = new_read_lock.m_top_ref; - hist.update_early_from_top_ref(new_version, new_file_size, new_top_ref); // Throws - } - - if (observer) { - // This has to happen in the context of the originally bound snapshot - // and while the read transaction is still in a fully functional state. - _impl::TransactLogParser parser; - version_type old_version = m_read_lock.m_version; - version_type new_version = new_read_lock.m_version; - _impl::ChangesetInputStream in(hist, old_version, new_version); - parser.parse(in, *observer); // Throws - observer->parse_complete(); // Throws - } - - // The old read lock must be retained for as long as the change history is - // accessed (until Group::advance_transact() returns). This ensures that the - // oldest needed changeset remains in the history, even when the history is - // implemented as a separate unversioned entity outside the Realm (i.e., the - // old implementation and ShortCircuitHistory in - // test_lang_Bind_helper.cpp). On the other hand, if it had been the case, - // that the history was always implemented as a versioned entity, that was - // part of the Realm state, then it would not have been necessary to retain - // the old read lock beyond this point. - - { - version_type old_version = m_read_lock.m_version; - version_type new_version = new_read_lock.m_version; - ref_type new_top_ref = new_read_lock.m_top_ref; - size_t new_file_size = new_read_lock.m_file_size; - _impl::ChangesetInputStream in(hist, old_version, new_version); - m_group.advance_transact(new_top_ref, new_file_size, in); // Throws - } - - g.release(); - release_read_lock(m_read_lock); - m_read_lock = new_read_lock; - - return true; // _impl::History::update_early_from_top_ref() was called -} - -inline _impl::History* SharedGroup::get_history() -{ - using gf = _impl::GroupFriend; - if (Replication* repl = gf::get_replication(m_group)) - return repl->get_history(); - return 0; -} - -inline int SharedGroup::get_file_format_version() const noexcept -{ - using gf = _impl::GroupFriend; - return gf::get_file_format_version(m_group); -} - - -// The purpose of this class is to give internal access to some, but -// not all of the non-public parts of the SharedGroup class. -class _impl::SharedGroupFriend { -public: - static Group& get_group(SharedGroup& sg) noexcept - { - return sg.m_group; - } - - template - static void advance_read(SharedGroup& sg, O* obs, SharedGroup::VersionID ver) - { - sg.advance_read(obs, ver); // Throws - } - - template - static void promote_to_write(SharedGroup& sg, O* obs) - { - sg.promote_to_write(obs); // Throws - } - - static SharedGroup::version_type commit_and_continue_as_read(SharedGroup& sg) - { - return sg.commit_and_continue_as_read(); // Throws - } - - template - static void rollback_and_continue_as_read(SharedGroup& sg, O* obs) - { - sg.rollback_and_continue_as_read(obs); // Throws - } - - static void async_daemon_open(SharedGroup& sg, const std::string& file) - { - bool no_create = true; - bool is_backend = true; - SharedGroupOptions options; - options.durability = SharedGroupOptions::Durability::Async; - options.encryption_key = nullptr; - options.allow_file_format_upgrade = false; - sg.do_open(file, no_create, is_backend, options); // Throws - } - - static int get_file_format_version(const SharedGroup& sg) noexcept - { - return sg.get_file_format_version(); - } - - static SharedGroup::version_type get_version_of_latest_snapshot(SharedGroup& sg) - { - return sg.get_version_of_latest_snapshot(); - } - - static SharedGroup::version_type get_version_of_bound_snapshot(const SharedGroup& sg) noexcept - { - return sg.get_version_of_bound_snapshot(); - } -}; - -inline const Group& ReadTransaction::get_group() const noexcept -{ - using sgf = _impl::SharedGroupFriend; - return sgf::get_group(m_shared_group); -} - -inline SharedGroup::version_type ReadTransaction::get_version() const noexcept -{ - using sgf = _impl::SharedGroupFriend; - return sgf::get_version_of_bound_snapshot(m_shared_group); -} - -inline Group& WriteTransaction::get_group() const noexcept -{ - REALM_ASSERT(m_shared_group); - using sgf = _impl::SharedGroupFriend; - return sgf::get_group(*m_shared_group); -} - -inline SharedGroup::version_type WriteTransaction::get_version() const noexcept -{ - using sgf = _impl::SharedGroupFriend; - return sgf::get_version_of_bound_snapshot(*m_shared_group); -} - -} // namespace realm - -#endif // REALM_GROUP_SHARED_HPP diff --git a/Example/Pods/Realm/include/core/realm/group_shared_options.hpp b/Example/Pods/Realm/include/core/realm/group_shared_options.hpp deleted file mode 100644 index 8430c44..0000000 --- a/Example/Pods/Realm/include/core/realm/group_shared_options.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_GROUP_SHARED_OPTIONS_HPP -#define REALM_GROUP_SHARED_OPTIONS_HPP - -#include -#include - -namespace realm { - -struct SharedGroupOptions { - - /// The persistence level of the SharedGroup. - /// uint16_t is the type of SharedGroup::SharedInfo::durability - enum class Durability : uint16_t { - Full, - MemOnly, - Async ///< Not yet supported on windows. - }; - - explicit SharedGroupOptions(Durability level = Durability::Full, const char* key = nullptr, - bool allow_upgrade = true, - std::function file_upgrade_callback = std::function(), - std::string temp_directory = sys_tmp_dir) - : durability(level) - , encryption_key(key) - , allow_file_format_upgrade(allow_upgrade) - , upgrade_callback(file_upgrade_callback) - , temp_dir(temp_directory) - { - } - - explicit SharedGroupOptions(const char* key) - : durability(Durability::Full) - , encryption_key(key) - , allow_file_format_upgrade(true) - , upgrade_callback(std::function()) - , temp_dir(sys_tmp_dir) - { - } - - /// The persistence level of the Realm file. See Durability. - Durability durability; - - /// The key to encrypt and decrypt the Realm file with, or nullptr to - /// indicate that encryption should not be used. - const char* encryption_key; - - /// If \a allow_file_format_upgrade is set to `true`, this function will - /// automatically upgrade the file format used in the specified Realm file - /// if necessary (and if it is possible). In order to prevent this, set \a - /// allow_upgrade to `false`. - /// - /// If \a allow_upgrade is set to `false`, only two outcomes are possible: - /// - /// - the specified Realm file is already using the latest file format, and - /// can be used, or - /// - /// - the specified Realm file uses a deprecated file format, resulting a - /// the throwing of FileFormatUpgradeRequired. - bool allow_file_format_upgrade; - - /// Optionally allows a custom function to be called immediately after the - /// Realm file is upgraded. The two parameters in the function are the - /// previous version and the version just upgraded to, respectively. - /// If the callback function throws, the Realm file will safely abort the - /// upgrade (rollback the transaction) but the SharedGroup will not be opened. - std::function upgrade_callback; - - /// A path to a directory where Realm can write temporary files or pipes to. - /// This string should include a trailing slash '/'. - std::string temp_dir; - -private: - const static std::string sys_tmp_dir; -}; - -} // end namespace realm - -#endif // REALM_GROUP_SHARED_OPTIONS_HPP diff --git a/Example/Pods/Realm/include/core/realm/group_writer.hpp b/Example/Pods/Realm/include/core/realm/group_writer.hpp deleted file mode 100644 index 424f293..0000000 --- a/Example/Pods/Realm/include/core/realm/group_writer.hpp +++ /dev/null @@ -1,164 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_GROUP_WRITER_HPP -#define REALM_GROUP_WRITER_HPP - -#include // unint8_t etc -#include - -#include -#include -#include -#include - - -namespace realm { - -// Pre-declarations -class Group; -class SlabAlloc; - - -/// This class is not supposed to be reused for multiple write sessions. In -/// particular, do not reuse it in case any of the functions throw. -/// -/// FIXME: Move this class to namespace realm::_impl and to subdir src/realm/impl. -class GroupWriter : public _impl::ArrayWriterBase { -public: - // For groups in transactional mode (Group::m_is_shared), this constructor - // must be called while a write transaction is in progress. - // - // The constructor adds free-space tracking information to the specified - // group, if it is not already present (4th and 5th entry in - // Group::m_top). If the specified group is in transactional mode - // (Group::m_is_shared), the constructor also adds version tracking - // information to the group, if it is not already present (6th and 7th entry - // in Group::m_top). - GroupWriter(Group&); - ~GroupWriter(); - - void set_versions(uint64_t current, uint64_t read_lock) noexcept; - - /// Write all changed array nodes into free space. - /// - /// Returns the new top ref. When in full durability mode, call - /// commit() with the returned top ref. - ref_type write_group(); - - /// Flush changes to physical medium, then write the new top ref - /// to the file header, then flush again. Pass the top ref - /// returned by write_group(). - void commit(ref_type new_top_ref); - - size_t get_file_size() const noexcept; - - /// Write the specified chunk into free space. - void write(const char* data, size_t size); - - ref_type write_array(const char*, size_t, uint32_t) override; - -#ifdef REALM_DEBUG - void dump(); -#endif - -private: - class MapWindow; - Group& m_group; - SlabAlloc& m_alloc; - ArrayInteger m_free_positions; // 4th slot in Group::m_top - ArrayInteger m_free_lengths; // 5th slot in Group::m_top - ArrayInteger m_free_versions; // 6th slot in Group::m_top - uint64_t m_current_version; - uint64_t m_readlock_version; - - // Currently cached memory mappings. We keep as many as 16 1MB windows - // open for writing. The allocator will favor sequential allocation - // from a modest number of windows, depending upon fragmentation, so - // 16 windows should be more than enough. If more than 16 windows are - // needed, the least recently used is sync'ed and closed to make room - // for a new one. The windows are kept in MRU (most recently used) order. - const static int num_map_windows = 16; - std::vector m_map_windows; - - // Get a suitable memory mapping for later access: - // potentially adding it to the cache, potentially closing - // the least recently used and sync'ing it to disk - MapWindow* get_window(ref_type start_ref, size_t size); - - // Sync all cached memory mappings - void sync_all_mappings(); - - // Merge adjacent chunks - void merge_free_space(); - - /// Allocate a chunk of free space of the specified size. The - /// specified size must be 8-byte aligned. Extend the file if - /// required. The returned chunk is removed from the amount of - /// remaing free space. The returned chunk is guaranteed to be - /// within a single contiguous memory mapping. - /// - /// \return The position within the database file of the allocated - /// chunk. - size_t get_free_space(size_t size); - - /// Find a block of free space that is at least as big as the - /// specified size and which will allow an allocation that is mapped - /// inside a contiguous address range. The specified size does not - /// need to be 8-byte aligned. Extend the file if required. - /// The returned chunk is not removed from the amount of remaing - /// free space. - /// - /// \return A pair (`chunk_ndx`, `chunk_size`) where `chunk_ndx` - /// is the index of a chunk whose size is at least the requestd - /// size, and `chunk_size` is the size of that chunk. - std::pair reserve_free_space(size_t size); - - /// Search only a range of the free list for a block as big as the - /// specified size. Return a pair with index and size of the found chunk. - /// \param found indicates whether a suitable block was found. - std::pair search_free_space_in_part_of_freelist(size_t size, size_t begin, size_t end, - bool& found); - - /// Extend the file to ensure that a chunk of free space of the - /// specified size is available. The specified size does not need - /// to be 8-byte aligned. This function guarantees that it will - /// add at most one entry to the free-lists. - /// - /// \return A pair (`chunk_ndx`, `chunk_size`) where `chunk_ndx` - /// is the index of a chunk whose size is at least the requestd - /// size, and `chunk_size` is the size of that chunk. - std::pair extend_free_space(size_t requested_size); - - void write_array_at(MapWindow* window, ref_type, const char* data, size_t size); - size_t split_freelist_chunk(size_t index, size_t start_pos, size_t alloc_pos, size_t chunk_size, bool is_shared); -}; - - -// Implementation: - -inline void GroupWriter::set_versions(uint64_t current, uint64_t read_lock) noexcept -{ - REALM_ASSERT(read_lock <= current); - m_current_version = current; - m_readlock_version = read_lock; -} - -} // namespace realm - -#endif // REALM_GROUP_WRITER_HPP diff --git a/Example/Pods/Realm/include/core/realm/handover_defs.hpp b/Example/Pods/Realm/include/core/realm/handover_defs.hpp deleted file mode 100644 index 6950bd5..0000000 --- a/Example/Pods/Realm/include/core/realm/handover_defs.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_HANDOVER_DEFS -#define REALM_HANDOVER_DEFS - -#include -#include - -namespace realm { - -enum class ConstSourcePayload { Copy, Stay }; -enum class MutableSourcePayload { Move }; - -struct RowBaseHandoverPatch; -struct TableViewHandoverPatch; - -struct TableHandoverPatch { - size_t m_table_num; -}; - -struct LinkViewHandoverPatch { - std::unique_ptr m_table; - size_t m_col_num; - size_t m_row_ndx; -}; - -// Base class for handover patches for query nodes. Subclasses are declared in query_engine.hpp. -struct QueryNodeHandoverPatch { - virtual ~QueryNodeHandoverPatch() = default; -}; - -using QueryNodeHandoverPatches = std::vector>; - -struct QueryHandoverPatch { - std::unique_ptr m_table; - std::unique_ptr table_view_data; - std::unique_ptr link_view_data; - QueryNodeHandoverPatches m_node_data; -}; - -struct SortDescriptorHandoverPatch { - std::vector> columns; - std::vector ascending; -}; - -struct TableViewHandoverPatch { - std::unique_ptr m_table; - std::unique_ptr linked_row; - size_t linked_col; - bool was_in_sync; - QueryHandoverPatch query_patch; - std::unique_ptr linkview_patch; - std::unique_ptr sort_patch; - std::unique_ptr distinct_patch; -}; - - -struct RowBaseHandoverPatch { - std::unique_ptr m_table; - size_t row_ndx; -}; - - -} // end namespace Realm - -#endif diff --git a/Example/Pods/Realm/include/core/realm/history.hpp b/Example/Pods/Realm/include/core/realm/history.hpp deleted file mode 100644 index 9710d0b..0000000 --- a/Example/Pods/Realm/include/core/realm/history.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_HISTORY_HPP -#define REALM_HISTORY_HPP - -#include -#include - -#include - - -namespace realm { - -std::unique_ptr make_in_realm_history(const std::string& realm_path); - -} // namespace realm - - -#endif // REALM_HISTORY_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/array_writer.hpp b/Example/Pods/Realm/include/core/realm/impl/array_writer.hpp deleted file mode 100644 index f039ad5..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/array_writer.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ARRAY_WRITER_HPP -#define REALM_ARRAY_WRITER_HPP - -#include - -namespace realm { -namespace _impl { - -class ArrayWriterBase { -public: - virtual ~ArrayWriterBase() - { - } - - /// Write the specified array data and its checksum into free - /// space. - /// - /// Returns the ref (position in the target stream) of the written copy of - /// the specified array data. - virtual ref_type write_array(const char* data, size_t size, uint32_t checksum) = 0; -}; - -} // namespace impl_ -} // namespace realm - -#endif // REALM_ARRAY_WRITER_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp b/Example/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp deleted file mode 100644 index c9e43bb..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp +++ /dev/null @@ -1,210 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_CONTINUOUS_TRANSACTIONS_HISTORY_HPP -#define REALM_IMPL_CONTINUOUS_TRANSACTIONS_HISTORY_HPP - -#include -#include - -#include -#include - -namespace realm { - -class Group; - -namespace _impl { - -/// Read-only access to history of changesets as needed to enable continuous -/// transactions. -class History { -public: - using version_type = VersionID::version_type; - - /// May be called during a read transaction to gain early access to the - /// history as it appears in a new snapshot that succeeds the one bound in - /// the current read transaction. - /// - /// May also be called at other times as long as the caller owns a read lock - /// (SharedGroup::grab_read_lock()) on the Realm for the specified file size - /// and top ref, and the allocator is in a 'free space clean' state - /// (SlabAlloc::is_free_space_clean()). - /// - /// This function may cause a remapping of the Realm file - /// (SlabAlloc::remap()) if it needs to make the new snapshot fully visible - /// in memory. - /// - /// Note that this method of gaining early access to the history in a new - /// snaphot only gives read access. It does not allow for modifications of - /// the history or any other part of the new snapshot. For modifications to - /// be allowed, `Group::m_top` (the parent of the history) would first have - /// to be updated to reflect the new snapshot, but at that time we are no - /// longer in an 'early access' situation. - /// - /// This is not a problem from the point of view of this history interface, - /// as it only contains methods for reading from the history, but some - /// implementations will want to also provide for ways to modify the - /// history, but in those cases, modifications must occur only after the - /// Group accessor has been fully updated to reflect the new snapshot. - virtual void update_early_from_top_ref(version_type new_version, size_t new_file_size, ref_type new_top_ref) = 0; - - virtual void update_from_parent(version_type current_version) = 0; - - /// Get all changesets between the specified versions. References to those - /// changesets will be made availble in successive entries of `buffer`. The - /// number of retreived changesets is exactly `end_version - - /// begin_version`. If this number is greater than zero, the changeset made - /// avaialable in `buffer[0]` is the one that brought the database from - /// `begin_version` to `begin_version + 1`. - /// - /// It is an error to specify a version (for \a begin_version or \a - /// end_version) that is outside the range [V,W] where V is the version that - /// immediately precedes the first changeset available in the history as the - /// history appears in the **latest** available snapshot, and W is the - /// versionm that immediately succeeds the last changeset available in the - /// history as the history appears in the snapshot bound to the **current** - /// transaction. This restriction is necessary to allow for different kinds - /// of implementations of the history (separate standalone history or - /// history as part of versioned Realm state). - /// - /// The calee retains ownership of the memory referenced by those entries, - /// i.e., the memory referenced by `buffer[i].changeset` is **not** handed - /// over to the caller. - /// - /// This function may be called only during a transaction (prior to - /// initiation of commit operation), and only after a successfull invocation - /// of update_early_from_top_ref(). In that case, the caller may assume that - /// the memory references stay valid for the remainder of the transaction - /// (up until initiation of the commit operation). - virtual void get_changesets(version_type begin_version, version_type end_version, BinaryIterator* buffer) const - noexcept = 0; - - /// \brief Specify the version of the oldest bound snapshot. - /// - /// This function must be called by the associated SharedGroup object during - /// each successfully committed write transaction. It must be called before - /// the transaction is finalized (Replication::finalize_commit()) or aborted - /// (Replication::abort_transact()), but after the initiation of the commit - /// operation (Replication::prepare_commit()). This allows history - /// implementations to add new history entries before triming off old ones, - /// and this, in turn, guarantees that the history never becomes empty, - /// except in the initial empty Realm state. - /// - /// The caller must pass the version (\a version) of the oldest snapshot - /// that is currently (or was recently) bound via a transaction of the - /// current session. This gives the history implementation an opportunity to - /// trim off leading (early) history entries. - /// - /// Since this function must be called during a write transaction, there - /// will always be at least one snapshot that is currently bound via a - /// transaction. - /// - /// The caller must guarantee that the passed version (\a version) is less - /// than or equal to `begin_version` in all future invocations of - /// get_changesets(). - /// - /// The caller is allowed to pass a version that is less than the version - /// passed in a preceeding invocation. - /// - /// This function should be called as late as possible, to maximize the - /// trimming opportunity, but at a time where the write transaction is still - /// open for additional modifications. This is necessary because some types - /// of histories are stored inside the Realm file. - virtual void set_oldest_bound_version(version_type version) = 0; - - /// Get the list of uncommited changes accumulated so far in the current - /// write transaction. - /// - /// The callee retains ownership of the referenced memory. The ownership is - /// not handed over the the caller. - /// - /// This function may be called only during a write transaction (prior to - /// initiation of commit operation). In that case, the caller may assume that the - /// returned memory reference stays valid for the remainder of the transaction (up - /// until initiation of the commit operation). - virtual BinaryData get_uncommitted_changes() noexcept = 0; - - virtual void verify() const = 0; - - virtual ~History() noexcept - { - } -}; - - -/// This class is intended to eventually become a basis for implementing the -/// Replication API for the purpose of supporting continuous transactions. That -/// is, its purpose is to replace the current implementation in commit_log.cpp, -/// which places the history in separate files. -/// -/// By ensuring that the root node of the history is correctly configured with -/// Group::m_top as its parent, this class allows for modifications of the -/// history as long as those modifications happen after the remainder of the -/// Group accessor is updated to reflect the new snapshot (see -/// History::update_early_from_top_ref()). -class InRealmHistory : public History { -public: - void initialize(Group&); - - /// Must never be called more than once per transaction. Returns the version - /// produced by the added changeset. - version_type add_changeset(BinaryData); - - void update_early_from_top_ref(version_type, size_t, ref_type) override; - void update_from_parent(version_type) override; - void get_changesets(version_type, version_type, BinaryIterator*) const noexcept override; - void set_oldest_bound_version(version_type) override; - - void verify() const override; - -private: - Group* m_group = nullptr; - - /// Version on which the first changeset in the history is based, or if the - /// history is empty, the version associatede with currently bound - /// snapshot. In general, the version associatede with currently bound - /// snapshot is equal to `m_base_version + m_size`, but after - /// add_changeset() is called, it is equal to one minus that. - version_type m_base_version; - - /// Current number of entries in the history. A cache of - /// `m_changesets->size()`. - size_t m_size; - - /// A list of changesets, one for each entry in the history. If null, the - /// history is empty. - /// - /// FIXME: Ideally, the B+tree accessor below should have been just - /// Bptree, but Bptree seems to not allow that yet. - /// - /// FIXME: The memory-wise indirection is an unfortunate consequence of the - /// fact that it is impossible to construct a BinaryColumn without already - /// having a ref to a valid underlying node structure. This, in turn, is an - /// unfortunate consequence of the fact that a column accessor contains a - /// dynamically allocated root node accessor, and the type of the required - /// root node accessor depends on the size of the B+-tree. - std::unique_ptr m_changesets; - - void update_from_ref(ref_type, version_type); -}; - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_CONTINUOUS_TRANSACTIONS_HISTORY_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/destroy_guard.hpp b/Example/Pods/Realm/include/core/realm/impl/destroy_guard.hpp deleted file mode 100644 index e744141..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/destroy_guard.hpp +++ /dev/null @@ -1,225 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_DESTROY_GUARD_HPP -#define REALM_IMPL_DESTROY_GUARD_HPP - -#include -#include - -namespace realm { -namespace _impl { - - -/// Calls `ptr->destroy()` if the guarded pointer (`ptr`) is not null -/// when the guard is destroyed. For arrays (`T` = `Array`) this means -/// that the array is destroyed in a shallow fashion. See -/// `DeepArrayDestroyGuard` for an alternative. -template -class DestroyGuard { -public: - DestroyGuard() noexcept; - - DestroyGuard(T*) noexcept; - - ~DestroyGuard() noexcept; - - void reset(T*) noexcept; - - T* get() const noexcept; - - T* release() noexcept; - -private: - T* m_ptr; -}; - -using ShallowArrayDestroyGuard = DestroyGuard; - - -/// Calls `ptr->destroy_deep()` if the guarded Array pointer (`ptr`) -/// is not null when the guard is destroyed. -class DeepArrayDestroyGuard { -public: - DeepArrayDestroyGuard() noexcept; - - DeepArrayDestroyGuard(Array*) noexcept; - - ~DeepArrayDestroyGuard() noexcept; - - void reset(Array*) noexcept; - - Array* get() const noexcept; - - Array* release() noexcept; - -private: - Array* m_ptr; -}; - - -/// Calls `Array::destroy_deep(ref, alloc)` if the guarded 'ref' -/// (`ref`) is not zero when the guard is destroyed. -class DeepArrayRefDestroyGuard { -public: - DeepArrayRefDestroyGuard(Allocator&) noexcept; - - DeepArrayRefDestroyGuard(ref_type, Allocator&) noexcept; - - ~DeepArrayRefDestroyGuard() noexcept; - - void reset(ref_type) noexcept; - - ref_type get() const noexcept; - - ref_type release() noexcept; - -private: - ref_type m_ref; - Allocator& m_alloc; -}; - - -// Implementation: - -// DestroyGuard - -template -inline DestroyGuard::DestroyGuard() noexcept - : m_ptr(nullptr) -{ -} - -template -inline DestroyGuard::DestroyGuard(T* ptr) noexcept - : m_ptr(ptr) -{ -} - -template -inline DestroyGuard::~DestroyGuard() noexcept -{ - if (m_ptr) - m_ptr->destroy(); -} - -template -inline void DestroyGuard::reset(T* ptr) noexcept -{ - if (m_ptr) - m_ptr->destroy(); - m_ptr = ptr; -} - -template -inline T* DestroyGuard::get() const noexcept -{ - return m_ptr; -} - -template -inline T* DestroyGuard::release() noexcept -{ - T* ptr = m_ptr; - m_ptr = nullptr; - return ptr; -} - - -// DeepArrayDestroyGuard - -inline DeepArrayDestroyGuard::DeepArrayDestroyGuard() noexcept - : m_ptr(nullptr) -{ -} - -inline DeepArrayDestroyGuard::DeepArrayDestroyGuard(Array* ptr) noexcept - : m_ptr(ptr) -{ -} - -inline DeepArrayDestroyGuard::~DeepArrayDestroyGuard() noexcept -{ - if (m_ptr) - m_ptr->destroy_deep(); -} - -inline void DeepArrayDestroyGuard::reset(Array* ptr) noexcept -{ - if (m_ptr) - m_ptr->destroy_deep(); - m_ptr = ptr; -} - -inline Array* DeepArrayDestroyGuard::get() const noexcept -{ - return m_ptr; -} - -inline Array* DeepArrayDestroyGuard::release() noexcept -{ - Array* ptr = m_ptr; - m_ptr = nullptr; - return ptr; -} - - -// DeepArrayRefDestroyGuard - -inline DeepArrayRefDestroyGuard::DeepArrayRefDestroyGuard(Allocator& alloc) noexcept - : m_ref(0) - , m_alloc(alloc) -{ -} - -inline DeepArrayRefDestroyGuard::DeepArrayRefDestroyGuard(ref_type ref, Allocator& alloc) noexcept - : m_ref(ref) - , m_alloc(alloc) -{ -} - -inline DeepArrayRefDestroyGuard::~DeepArrayRefDestroyGuard() noexcept -{ - if (m_ref) - Array::destroy_deep(m_ref, m_alloc); -} - -inline void DeepArrayRefDestroyGuard::reset(ref_type ref) noexcept -{ - if (m_ref) - Array::destroy_deep(m_ref, m_alloc); - m_ref = ref; -} - -inline ref_type DeepArrayRefDestroyGuard::get() const noexcept -{ - return m_ref; -} - -inline ref_type DeepArrayRefDestroyGuard::release() noexcept -{ - ref_type ref = m_ref; - m_ref = 0; - return ref; -} - - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_DESTROY_GUARD_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/input_stream.hpp b/Example/Pods/Realm/include/core/realm/impl/input_stream.hpp deleted file mode 100644 index c973841..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/input_stream.hpp +++ /dev/null @@ -1,256 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_INPUT_STREAM_HPP -#define REALM_IMPL_INPUT_STREAM_HPP - -#include - -#include -#include -#include - - -namespace realm { -namespace _impl { - - -class InputStream { -public: - /// Read bytes from this input stream and place them in the specified - /// buffer. The returned value is the actual number of bytes that were read, - /// and this is some number `n` such that `n <= min(size, m)` where `m` is - /// the number of bytes that could have been read from this stream before - /// reaching its end. Also, `n` cannot be zero unless `m` or `size` is - /// zero. The intention is that `size` should be non-zero, a the return - /// value used as the end-of-input indicator. - /// - /// Implementations are only allowed to block (put the calling thread to - /// sleep) up until the point in time where the first byte can be made - /// availble. - virtual size_t read(char* buffer, size_t size) = 0; - - virtual ~InputStream() noexcept - { - } -}; - - -class SimpleInputStream : public InputStream { -public: - SimpleInputStream(const char* data, size_t size) noexcept - : m_ptr(data) - , m_end(data + size) - { - } - size_t read(char* buffer, size_t size) override - { - size_t n = std::min(size, size_t(m_end - m_ptr)); - const char* begin = m_ptr; - m_ptr += n; - const char* end = m_ptr; - std::copy(begin, end, buffer); - return n; - } - -private: - const char* m_ptr; - const char* const m_end; -}; - - -class NoCopyInputStream { -public: - /// \return if any bytes was read. - /// A value of false indicates end-of-input. - /// If return value is true, \a begin and \a end are - /// updated to reflect the start and limit of a - /// contiguous memory chunk. - virtual bool next_block(const char*& begin, const char*& end) = 0; - - virtual ~NoCopyInputStream() noexcept - { - } -}; - - -class NoCopyInputStreamAdaptor : public NoCopyInputStream { -public: - NoCopyInputStreamAdaptor(InputStream& in, char* buffer, size_t buffer_size) noexcept - : m_in(in) - , m_buffer(buffer) - , m_buffer_size(buffer_size) - { - } - bool next_block(const char*& begin, const char*& end) override - { - size_t n = m_in.read(m_buffer, m_buffer_size); - begin = m_buffer; - end = m_buffer + n; - return n; - } - -private: - InputStream& m_in; - char* m_buffer; - size_t m_buffer_size; -}; - - -class SimpleNoCopyInputStream : public NoCopyInputStream { -public: - SimpleNoCopyInputStream(const char* data, size_t size) - : m_data(data) - , m_size(size) - { - } - - bool next_block(const char*& begin, const char*& end) override - { - if (m_size == 0) - return 0; - size_t size = m_size; - begin = m_data; - end = m_data + size; - m_size = 0; - return size; - } - -private: - const char* m_data; - size_t m_size; -}; - -class MultiLogNoCopyInputStream : public NoCopyInputStream { -public: - MultiLogNoCopyInputStream(const BinaryData* logs_begin, const BinaryData* logs_end) - : m_logs_begin(logs_begin) - , m_logs_end(logs_end) - { - if (m_logs_begin != m_logs_end) - m_curr_buf_remaining_size = m_logs_begin->size(); - } - - size_t read(char* buffer, size_t size) - { - if (m_logs_begin == m_logs_end) - return 0; - for (;;) { - if (m_curr_buf_remaining_size > 0) { - size_t offset = m_logs_begin->size() - m_curr_buf_remaining_size; - const char* data = m_logs_begin->data() + offset; - size_t size_2 = std::min(m_curr_buf_remaining_size, size); - m_curr_buf_remaining_size -= size_2; - // FIXME: Eliminate the need for copying by changing the API of - // Replication::InputStream such that blocks can be handed over - // without copying. This is a straight forward change, but the - // result is going to be more complicated and less conventional. - std::copy(data, data + size_2, buffer); - return size_2; - } - - ++m_logs_begin; - if (m_logs_begin == m_logs_end) - return 0; - m_curr_buf_remaining_size = m_logs_begin->size(); - } - } - - bool next_block(const char*& begin, const char*& end) override - { - while (m_logs_begin < m_logs_end) { - size_t result = m_logs_begin->size(); - const char* data = m_logs_begin->data(); - m_logs_begin++; - if (result == 0) - continue; // skip empty blocks - begin = data; - end = data + result; - return result; - } - return 0; - } - -private: - const BinaryData* m_logs_begin; - const BinaryData* m_logs_end; - size_t m_curr_buf_remaining_size; -}; - - -class ChangesetInputStream : public NoCopyInputStream { -public: - using version_type = History::version_type; - static constexpr unsigned NB_BUFFERS = 8; - - ChangesetInputStream(History& hist, version_type begin_version, version_type end_version) - : m_history(hist) - , m_begin_version(begin_version) - , m_end_version(end_version) - { - get_changeset(); - } - - bool next_block(const char*& begin, const char*& end) override - { - while (m_valid) { - BinaryData actual = m_changesets_begin->get_next(); - - if (actual.size() > 0) { - begin = actual.data(); - end = actual.data() + actual.size(); - return true; - } - - m_changesets_begin++; - - if (REALM_UNLIKELY(m_changesets_begin == m_changesets_end)) { - get_changeset(); - } - } - return false; // End of input - } - -private: - History& m_history; - version_type m_begin_version, m_end_version; - BinaryIterator m_changesets[NB_BUFFERS]; // Buffer - BinaryIterator* m_changesets_begin = nullptr; - BinaryIterator* m_changesets_end = nullptr; - bool m_valid; - - void get_changeset() - { - auto versions_to_get = m_end_version - m_begin_version; - m_valid = versions_to_get > 0; - if (m_valid) { - if (versions_to_get > NB_BUFFERS) - versions_to_get = NB_BUFFERS; - version_type end_version = m_begin_version + versions_to_get; - m_history.get_changesets(m_begin_version, end_version, m_changesets); - m_begin_version = end_version; - m_changesets_begin = m_changesets; - m_changesets_end = m_changesets_begin + versions_to_get; - } - } -}; - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_INPUT_STREAM_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/instructions.hpp b/Example/Pods/Realm/include/core/realm/impl/instructions.hpp deleted file mode 100644 index 9f54d81..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/instructions.hpp +++ /dev/null @@ -1,380 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#ifndef REALM_IMPL_INSTRUCTIONS_HPP -#define REALM_IMPL_INSTRUCTIONS_HPP - -#include // size_t -#include - -#include -#include -#include -#include -#include - -namespace realm { -namespace _impl { - -class TransactLogParser; -class TransactLogEncoder; -class InputStream; - -#define REALM_FOR_EACH_INSTRUCTION_TYPE(X) \ - X(SelectTable) \ - X(SelectDescriptor) \ - X(SelectLinkList) \ - X(InsertGroupLevelTable) \ - X(EraseGroupLevelTable) \ - X(RenameGroupLevelTable) \ - X(MoveGroupLevelTable) \ - X(InsertEmptyRows) \ - X(Remove) \ - X(MoveLastOver) \ - X(Swap) \ - X(MergeRows) \ - X(Set) \ - X(SetDefault) \ - X(SetUnique) \ - X(AddInteger) \ - X(InsertSubstring) \ - X(EraseSubstring) \ - X(ClearTable) \ - X(OptimizeTable) \ - X(InsertColumn) \ - X(EraseColumn) \ - X(RenameColumn) \ - X(MoveColumn) \ - X(AddSearchIndex) \ - X(RemoveSearchIndex) \ - X(SetLinkType) \ - X(LinkListSet) \ - X(LinkListInsert) \ - X(LinkListMove) \ - X(LinkListSwap) \ - X(LinkListErase) \ - X(LinkListClear) \ - - -enum class InstrType { -#define REALM_DEFINE_INSTRUCTION_TYPE(X) X, -REALM_FOR_EACH_INSTRUCTION_TYPE(REALM_DEFINE_INSTRUCTION_TYPE) -#undef REALM_DEFINE_INSTRUCTION_TYPE -}; - -struct StringBufferRange { - size_t offset, size; -}; - - -// Note: All specializations must be "POD", so that they can be -// part of a union. -template struct Instr; - -template <> struct Instr { - size_t group_level_ndx; - size_t num_pairs; - size_t pairs[2]; // FIXME: max 1 level of subtables -}; - -template <> struct Instr { - size_t num_pairs; - size_t pairs[2]; // FIXME: max 1 level of subtables -}; - -template <> struct Instr { - size_t col_ndx; - size_t row_ndx; - size_t link_target_group_level_ndx; -}; - -template <> struct Instr { - Instr() {} - size_t table_ndx; - size_t num_tables; - StringBufferRange name; -}; - -template <> struct Instr { - size_t table_ndx; - size_t num_tables; -}; - -template <> struct Instr { - size_t table_ndx; - StringBufferRange new_name; -}; - -template <> struct Instr { - size_t table_ndx_1; - size_t table_ndx_2; -}; - -template <> struct Instr { - size_t row_ndx; - size_t num_rows_to_insert; - size_t prior_num_rows; -}; - -template <> struct Instr { - size_t row_ndx; - size_t num_rows_to_erase; - size_t prior_num_rows; -}; - -template <> struct Instr { - size_t row_ndx; - size_t num_rows_to_erase; - size_t prior_num_rows; -}; - -template <> struct Instr { - size_t row_ndx_1; - size_t row_ndx_2; -}; - -template <> struct Instr { - size_t row_ndx; - size_t new_row_ndx; -}; - -template <> struct Instr { - size_t col_ndx; - size_t row_ndx; - - struct Payload { - DataType type; - - struct LinkPayload { - size_t target_row; // npos means null - size_t target_group_level_ndx; - bool implicit_nullify; - }; - - union PayloadData { - bool boolean; - int64_t integer; - float fnum; - double dnum; - StringBufferRange str; - Timestamp timestamp; - LinkPayload link; - - PayloadData() {} - PayloadData(const PayloadData&) = default; - PayloadData& operator=(const PayloadData&) = default; - }; - PayloadData data; - - bool is_null() const; - }; - - Payload payload; -}; - -template <> struct Instr { - size_t col_ndx; - size_t row_ndx; - int64_t value; -}; - -template <> struct Instr : Instr { -}; - -template <> struct Instr : Instr { - size_t prior_num_rows; -}; - -template<> struct Instr { - Instr() {} - size_t col_ndx; - size_t row_ndx; - size_t pos; - StringBufferRange value; -}; - -template<> struct Instr { - Instr() {} - size_t col_ndx; - size_t row_ndx; - size_t pos; - size_t size; -}; - -template <> struct Instr { -}; - -template <> struct Instr { -}; - -template <> struct Instr { - size_t link_ndx; - size_t value; - size_t prior_size; -}; - -template <> struct Instr { - size_t link_ndx; - size_t value; - size_t prior_size; -}; - -template <> struct Instr { - size_t link_ndx_1; - size_t link_ndx_2; -}; - -template <> struct Instr { - size_t link_ndx; - bool implicit_nullify; - size_t prior_size; -}; - -template <> struct Instr { - size_t link_ndx_1; - size_t link_ndx_2; -}; - -template <> struct Instr { - size_t num_links; -}; - -template <> struct Instr { - size_t col_ndx; - DataType type; - StringBufferRange name; - size_t link_target_table_ndx; - size_t backlink_col_ndx; - bool nullable; -}; - -template <> struct Instr { - size_t col_ndx; - size_t link_target_table_ndx; - size_t backlink_col_ndx; -}; - -template <> struct Instr { - size_t col_ndx; - StringBufferRange new_name; -}; - -template <> struct Instr { - size_t col_ndx_1; - size_t col_ndx_2; -}; - -template <> struct Instr { - size_t col_ndx; -}; - -template <> struct Instr { - size_t col_ndx; -}; - -template <> struct Instr { - size_t col_ndx; - LinkType type; -}; - -struct AnyInstruction { - using Type = InstrType; - - AnyInstruction() {} - template - AnyInstruction(Instr instr): type(t) - { - get_as() = std::move(instr); - } - - InstrType type; - union InstrUnion { -#define REALM_DEFINE_INSTRUCTION_MEMBER(X) Instr m_ ## X; - REALM_FOR_EACH_INSTRUCTION_TYPE(REALM_DEFINE_INSTRUCTION_MEMBER) -#undef REALM_DEFINE_INSTRUCTION_MEMBER - - InstrUnion() { -#if defined(REALM_DEBUG) - char* mem = reinterpret_cast(this); - std::fill(mem, mem + sizeof(*this), 0xef); -#endif // REALM_DEBUG - } - - InstrUnion(const InstrUnion&) = default; - InstrUnion& operator=(const InstrUnion&) = default; - }; - InstrUnion instr; - - template - void visit(F lambda); - template - void visit(F lambda) const; - - template Instr& get_as(); - - template - const Instr& get_as() const - { - return const_cast(this)->template get_as(); - } -}; - -#define REALM_DEFINE_GETTER(X) \ - template<> inline Instr& AnyInstruction::get_as() \ - { \ - return instr.m_ ## X; \ - } - REALM_FOR_EACH_INSTRUCTION_TYPE(REALM_DEFINE_GETTER) -#undef REALM_DEFINE_GETTER - -using InstructionList = std::vector; // FIXME: Consider using std::deque - -InstructionList parse_changeset_as_instructions(_impl::TransactLogParser&, _impl::InputStream&, - util::StringBuffer&); -void encode_instructions_as_changeset(const InstructionList&, const util::StringBuffer&, - _impl::TransactLogEncoder&); - - - - -/// Implementation: - -template -void AnyInstruction::visit(F lambda) -{ - switch (type) { -#define REALM_VISIT_INSTRUCTION(X) \ - case InstrType::X: return lambda(get_as()); - REALM_FOR_EACH_INSTRUCTION_TYPE(REALM_VISIT_INSTRUCTION) -#undef REALM_VISIT_INSTRUCTION - } - REALM_UNREACHABLE(); -} - -template -void AnyInstruction::visit(F lambda) const -{ - const_cast(this)->visit(lambda); -} - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_INSTRUCTIONS_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/output_stream.hpp b/Example/Pods/Realm/include/core/realm/impl/output_stream.hpp deleted file mode 100644 index 1d022cd..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/output_stream.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_OUTPUT_STREAM_HPP -#define REALM_IMPL_OUTPUT_STREAM_HPP - -#include -#include - -#include - -#include - -#include - -namespace realm { -namespace _impl { - - -class OutputStream : public ArrayWriterBase { -public: - OutputStream(std::ostream&); - ~OutputStream() noexcept; - - ref_type get_ref_of_next_array() const noexcept; - - void write(const char* data, size_t size); - - ref_type write_array(const char* data, size_t size, uint32_t checksum) override; - -private: - ref_type m_next_ref; - std::ostream& m_out; - - void do_write(const char* data, size_t size); -}; - - -// Implementation: - -inline OutputStream::OutputStream(std::ostream& out) - : m_next_ref(0) - , m_out(out) -{ -} - -inline OutputStream::~OutputStream() noexcept -{ -} - -inline size_t OutputStream::get_ref_of_next_array() const noexcept -{ - return m_next_ref; -} - - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_OUTPUT_STREAM_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/sequential_getter.hpp b/Example/Pods/Realm/include/core/realm/impl/sequential_getter.hpp deleted file mode 100644 index c6c8a21..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/sequential_getter.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_SEQUENTIAL_GETTER_HPP -#define REALM_IMPL_SEQUENTIAL_GETTER_HPP - -namespace realm { - -class SequentialGetterBase { -public: - virtual ~SequentialGetterBase() noexcept - { - } -}; - -template -class SequentialGetter : public SequentialGetterBase { -public: - using T = typename ColType::value_type; - using ArrayType = typename ColType::LeafType; - - SequentialGetter() - { - } - - SequentialGetter(const Table& table, size_t column_ndx) - { - if (column_ndx != not_found) - m_column = static_cast(&table.get_column_base(column_ndx)); - init(m_column); - } - - SequentialGetter(const ColType* column) - { - init(column); - } - - ~SequentialGetter() noexcept override - { - } - - void init(const ColType* column) - { - m_array_ptr.reset(); // Explicitly destroy the old one first, because we're reusing the memory. - m_array_ptr.reset(new (&m_leaf_accessor_storage) ArrayType(column->get_alloc())); - m_column = column; - m_leaf_end = 0; - } - - REALM_FORCEINLINE bool cache_next(size_t index) - { - // Set m_leaf_ptr to point at the leaf that contains the value at column row `index`. Return whether or not - // the leaf has changed (could be useful to know for caller). - - // FIXME: Below line has been commented away because array leafs might relocate during the lifetime of the - // object that owns this SequentialGetter. Enable again when we have proper support for that. -// if (index >= m_leaf_end || index < m_leaf_start) - { - typename ColType::LeafInfo leaf{&m_leaf_ptr, m_array_ptr.get()}; - size_t ndx_in_leaf; - m_column->get_leaf(index, ndx_in_leaf, leaf); - m_leaf_start = index - ndx_in_leaf; - const size_t leaf_size = m_leaf_ptr->size(); - m_leaf_end = m_leaf_start + leaf_size; - return true; - } - return false; - } - - - REALM_FORCEINLINE T get_next(size_t index) - { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4800) // Disable the Microsoft warning about bool performance issue. -#endif - return m_column->get(index); - - // FIXME: Below optimization is skipped because array leafs might relocate during the lifetime of the - // object that owns this SequentialGetter. Enable again when we have proper support for that. - cache_next(index); - T av = m_leaf_ptr->get(index - m_leaf_start); - return av; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - } - - size_t local_end(size_t global_end) - { - if (global_end > m_leaf_end) - return m_leaf_end - m_leaf_start; - else - return global_end - m_leaf_start; - } - - size_t m_leaf_start; - size_t m_leaf_end; - const ColType* m_column = nullptr; - - const ArrayType* m_leaf_ptr = nullptr; - -private: - // Leaf cache for when the root of the column is not a leaf. - // This dog and pony show is because Array has a reference to Allocator internally, - // but we need to be able to transfer queries between contexts, so init() reinitializes - // the leaf cache in the context of the current column. - typename std::aligned_storage::type m_leaf_accessor_storage; - std::unique_ptr m_array_ptr; -}; - -} // namespace realm - -#endif // REALM_IMPL_SEQUENTIAL_GETTER_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/simulated_failure.hpp b/Example/Pods/Realm/include/core/realm/impl/simulated_failure.hpp deleted file mode 100644 index af8ed19..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/simulated_failure.hpp +++ /dev/null @@ -1,229 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_SIMULATED_FAILURE_HPP -#define REALM_IMPL_SIMULATED_FAILURE_HPP - -#include -#include - -#include - -#ifdef REALM_DEBUG -#define REALM_ENABLE_SIMULATED_FAILURE -#endif - -namespace realm { -namespace _impl { - -class SimulatedFailure : public std::system_error { -public: - enum FailureType { - generic, - slab_alloc__reset_free_space_tracking, - slab_alloc__remap, - shared_group__grow_reader_mapping, - sync_client__read_head, - sync_server__read_head, - _num_failure_types - }; - - class OneShotPrimeGuard; - class RandomPrimeGuard; - - /// Prime the specified failure type on the calling thread for triggering - /// once. - static void prime_one_shot(FailureType); - - /// Prime the specified failure type on the calling thread for triggering - /// randomly \a n out of \a m times. - static void prime_random(FailureType, int n, int m, uint_fast64_t seed = 0); - - /// Unprime the specified failure type on the calling thread. - static void unprime(FailureType) noexcept; - - /// Returns true according to the mode of priming of the specified failure - /// type on the calling thread, but only if REALM_ENABLE_SIMULATED_FAILURE - /// was defined during compilation. If REALM_ENABLE_SIMULATED_FAILURE was - /// not defined, this function always return false. - static bool check_trigger(FailureType) noexcept; - - /// The specified error code is set to `make_error_code(failure_type)` if - /// check_trigger() returns true. Otherwise it is set to - /// `std::error_code()`. Returns a copy of the updated error code. - static std::error_code trigger(FailureType failure_type, std::error_code&) noexcept; - - /// Throws SimulatedFailure if check_trigger() returns true. The exception - /// will be constructed with an error code equal to - /// `make_error_code(failure_type)`. - static void trigger(FailureType failure_type); - - /// Returns true when, and only when REALM_ENABLE_SIMULATED_FAILURE was - /// defined during compilation. - static constexpr bool is_enabled(); - - SimulatedFailure(std::error_code); - -private: -#ifdef REALM_ENABLE_SIMULATED_FAILURE - static void do_prime_one_shot(FailureType); - static void do_prime_random(FailureType, int n, int m, uint_fast64_t seed); - static void do_unprime(FailureType) noexcept; - static bool do_check_trigger(FailureType) noexcept; -#endif -}; - - -class SimulatedFailure::OneShotPrimeGuard { -public: - OneShotPrimeGuard(FailureType); - ~OneShotPrimeGuard() noexcept; - -private: - const FailureType m_type; -}; - - -class SimulatedFailure::RandomPrimeGuard { -public: - RandomPrimeGuard(FailureType, int n, int m, uint_fast64_t seed = 0); - ~RandomPrimeGuard() noexcept; - -private: - const FailureType m_type; -}; - - -std::error_code make_error_code(SimulatedFailure::FailureType) noexcept; - -} // namespace _impl -} // namespace realm - -namespace std { - -template<> struct is_error_code_enum { - static const bool value = true; -}; - -} // namespace std - -namespace realm { -namespace _impl { - - - -// Implementation - -inline void SimulatedFailure::prime_one_shot(FailureType failure_type) -{ -#ifdef REALM_ENABLE_SIMULATED_FAILURE - do_prime_one_shot(failure_type); -#else - static_cast(failure_type); -#endif -} - -inline void SimulatedFailure::prime_random(FailureType failure_type, int n, int m, uint_fast64_t seed) -{ -#ifdef REALM_ENABLE_SIMULATED_FAILURE - do_prime_random(failure_type, n, m, seed); -#else - static_cast(failure_type); - static_cast(n); - static_cast(m); - static_cast(seed); -#endif -} - -inline void SimulatedFailure::unprime(FailureType failure_type) noexcept -{ -#ifdef REALM_ENABLE_SIMULATED_FAILURE - do_unprime(failure_type); -#else - static_cast(failure_type); -#endif -} - -inline bool SimulatedFailure::check_trigger(FailureType failure_type) noexcept -{ -#ifdef REALM_ENABLE_SIMULATED_FAILURE - return do_check_trigger(failure_type); -#else - static_cast(failure_type); - return false; -#endif -} - -inline std::error_code SimulatedFailure::trigger(FailureType failure_type, std::error_code& ec) noexcept -{ - if (check_trigger(failure_type)) { - ec = make_error_code(failure_type); - } - else { - ec = std::error_code(); - } - return ec; -} - -inline void SimulatedFailure::trigger(FailureType failure_type) -{ - if (check_trigger(failure_type)) - throw SimulatedFailure(make_error_code(failure_type)); -} - -inline constexpr bool SimulatedFailure::is_enabled() -{ -#ifdef REALM_ENABLE_SIMULATED_FAILURE - return true; -#else - return false; -#endif -} - -inline SimulatedFailure::SimulatedFailure(std::error_code ec) - : std::system_error(ec) -{ -} - -inline SimulatedFailure::OneShotPrimeGuard::OneShotPrimeGuard(FailureType failure_type) - : m_type(failure_type) -{ - prime_one_shot(m_type); -} - -inline SimulatedFailure::OneShotPrimeGuard::~OneShotPrimeGuard() noexcept -{ - unprime(m_type); -} - -inline SimulatedFailure::RandomPrimeGuard::RandomPrimeGuard(FailureType failure_type, int n, int m, - uint_fast64_t seed) - : m_type(failure_type) -{ - prime_random(m_type, n, m, seed); -} - -inline SimulatedFailure::RandomPrimeGuard::~RandomPrimeGuard() noexcept -{ - unprime(m_type); -} - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_SIMULATED_FAILURE_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/table_path.hpp b/Example/Pods/Realm/include/core/realm/impl/table_path.hpp deleted file mode 100644 index c03b6cb..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/table_path.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2012] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#ifndef REALM_IMPL_TABLE_PATH_HPP -#define REALM_IMPL_TABLE_PATH_HPP - -#include -#include -#include - -namespace realm { -namespace _impl { - -class TablePath { -public: - TablePath() - { - } - - TablePath(const size_t* begin, size_t len) : m_coords(begin, begin + len) - { - } - - TablePath(size_t group_level_ndx, size_t num_pairs, const size_t* pairs) - { - m_coords.reserve(num_pairs * 2 + 1); - m_coords.push_back(group_level_ndx); - std::copy(pairs, pairs + num_pairs * 2, std::back_inserter(m_coords)); - } - - bool operator==(const TablePath& other) const - { - if (m_coords.size() != other.m_coords.size()) { - return false; - } - for (size_t i = 0; i < m_coords.size(); ++i) { - if (m_coords[i] != other.m_coords[i]) { - return false; - } - } - return true; - } - - bool operator!=(const TablePath& other) const - { - return !((*this) == other); - } - - void push(size_t coord) - { - m_coords.push_back(coord); - } - - size_t size() const - { - return m_coords.size(); - } - - void clear() - { - m_coords.clear(); - } - - // FIXME: Should be private, but is accessed directly from sync.cpp. - std::vector m_coords; -}; - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_TABLE_PATH_HPP diff --git a/Example/Pods/Realm/include/core/realm/impl/transact_log.hpp b/Example/Pods/Realm/include/core/realm/impl/transact_log.hpp deleted file mode 100644 index fa748a1..0000000 --- a/Example/Pods/Realm/include/core/realm/impl/transact_log.hpp +++ /dev/null @@ -1,2772 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPL_TRANSACT_LOG_HPP -#define REALM_IMPL_TRANSACT_LOG_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace realm { -namespace _impl { - -/// Transaction log instruction encoding -/// NOTE: Any change to this enum is a file-format breaking change. -enum Instruction { - instr_InsertGroupLevelTable = 1, - instr_EraseGroupLevelTable = 2, // Remove columnless table from group - instr_RenameGroupLevelTable = 3, - instr_MoveGroupLevelTable = 4, - instr_SelectTable = 5, - instr_Set = 6, - instr_SetUnique = 7, - instr_SetDefault = 8, - instr_AddInteger = 9, // Add value to integer field - instr_NullifyLink = 10, // Set link to null due to target being erased - instr_InsertSubstring = 11, - instr_EraseFromString = 12, - instr_InsertEmptyRows = 13, - instr_EraseRows = 14, // Remove (multiple) rows - instr_SwapRows = 15, - instr_MergeRows = 16, // Replace links pointing to row A with links to row B - instr_ClearTable = 17, // Remove all rows in selected table - instr_OptimizeTable = 18, - instr_SelectDescriptor = 19, // Select descriptor from currently selected root table - instr_InsertColumn = - 20, // Insert new non-nullable column into to selected descriptor (nullable is instr_InsertNullableColumn) - instr_InsertLinkColumn = 21, // do, but for a link-type column - instr_InsertNullableColumn = 22, // Insert nullable column - instr_EraseColumn = 23, // Remove column from selected descriptor - instr_EraseLinkColumn = 24, // Remove link-type column from selected descriptor - instr_RenameColumn = 25, // Rename column in selected descriptor - instr_MoveColumn = 26, // Move column in selected descriptor - instr_AddSearchIndex = 27, // Add a search index to a column - instr_RemoveSearchIndex = 28, // Remove a search index from a column - instr_SetLinkType = 29, // Strong/weak - instr_SelectLinkList = 30, - instr_LinkListSet = 31, // Assign to link list entry - instr_LinkListInsert = 32, // Insert entry into link list - instr_LinkListMove = 33, // Move an entry within a link list - instr_LinkListSwap = 34, // Swap two entries within a link list - instr_LinkListErase = 35, // Remove an entry from a link list - instr_LinkListNullify = 36, // Remove an entry from a link list due to linked row being erased - instr_LinkListClear = 37, // Ramove all entries from a link list - instr_LinkListSetAll = 38, // Assign to link list entry -}; - - -class TransactLogStream { -public: - /// Ensure contiguous free space in the transaction log - /// buffer. This method must update `out_free_begin` - /// and `out_free_end` such that they refer to a chunk - /// of free space whose size is at least \a n. - /// - /// \param n The required amount of contiguous free space. Must be - /// small (probably not greater than 1024) - /// \param n Must be small (probably not greater than 1024) - virtual void transact_log_reserve(size_t size, char** out_free_begin, char** out_free_end) = 0; - - /// Copy the specified data into the transaction log buffer. This - /// function should be called only when the specified data does - /// not fit inside the chunk of free space currently referred to - /// by `out_free_begin` and `out_free_end`. - /// - /// This method must update `out_begin` and - /// `out_end` such that, upon return, they still - /// refer to a (possibly empty) chunk of free space. - virtual void transact_log_append(const char* data, size_t size, char** out_free_begin, char** out_free_end) = 0; -}; - -class TransactLogBufferStream : public TransactLogStream { -public: - void transact_log_reserve(size_t size, char** out_free_begin, char** out_free_end) override; - void transact_log_append(const char* data, size_t size, char** out_free_begin, char** out_free_end) override; - - const char* transact_log_data() const; - - util::Buffer m_buffer; -}; - - -// LCOV_EXCL_START (because the NullInstructionObserver is trivial) -class NullInstructionObserver { -public: - /// The following methods are also those that TransactLogParser expects - /// to find on the `InstructionHandler`. - - // No selection needed: - bool select_table(size_t, size_t, const size_t*) - { - return true; - } - bool select_descriptor(size_t, const size_t*) - { - return true; - } - bool select_link_list(size_t, size_t, size_t) - { - return true; - } - bool insert_group_level_table(size_t, size_t, StringData) - { - return true; - } - bool erase_group_level_table(size_t, size_t) - { - return true; - } - bool rename_group_level_table(size_t, StringData) - { - return true; - } - bool move_group_level_table(size_t, size_t) - { - return true; - } - - // Must have table selected: - bool insert_empty_rows(size_t, size_t, size_t, bool) - { - return true; - } - bool erase_rows(size_t, size_t, size_t, bool) - { - return true; - } - bool swap_rows(size_t, size_t) - { - return true; - } - bool merge_rows(size_t, size_t) - { - return true; - } - bool clear_table() - { - return true; - } - bool set_int(size_t, size_t, int_fast64_t, Instruction, size_t) - { - return true; - } - bool add_int(size_t, size_t, int_fast64_t) - { - return true; - } - bool set_bool(size_t, size_t, bool, Instruction) - { - return true; - } - bool set_float(size_t, size_t, float, Instruction) - { - return true; - } - bool set_double(size_t, size_t, double, Instruction) - { - return true; - } - bool set_string(size_t, size_t, StringData, Instruction, size_t) - { - return true; - } - bool set_binary(size_t, size_t, BinaryData, Instruction) - { - return true; - } - bool set_olddatetime(size_t, size_t, OldDateTime, Instruction) - { - return true; - } - bool set_timestamp(size_t, size_t, Timestamp, Instruction) - { - return true; - } - bool set_table(size_t, size_t, Instruction) - { - return true; - } - bool set_mixed(size_t, size_t, const Mixed&, Instruction) - { - return true; - } - bool set_link(size_t, size_t, size_t, size_t, Instruction) - { - return true; - } - bool set_null(size_t, size_t, Instruction, size_t) - { - return true; - } - bool nullify_link(size_t, size_t, size_t) - { - return true; - } - bool insert_substring(size_t, size_t, size_t, StringData) - { - return true; - } - bool erase_substring(size_t, size_t, size_t, size_t) - { - return true; - } - bool optimize_table() - { - return true; - } - - // Must have descriptor selected: - bool insert_link_column(size_t, DataType, StringData, size_t, size_t) - { - return true; - } - bool insert_column(size_t, DataType, StringData, bool) - { - return true; - } - bool erase_link_column(size_t, size_t, size_t) - { - return true; - } - bool erase_column(size_t) - { - return true; - } - bool rename_column(size_t, StringData) - { - return true; - } - bool move_column(size_t, size_t) - { - return true; - } - bool add_search_index(size_t) - { - return true; - } - bool remove_search_index(size_t) - { - return true; - } - bool set_link_type(size_t, LinkType) - { - return true; - } - - // Must have linklist selected: - bool link_list_set(size_t, size_t, size_t) - { - return true; - } - bool link_list_insert(size_t, size_t, size_t) - { - return true; - } - bool link_list_move(size_t, size_t) - { - return true; - } - bool link_list_swap(size_t, size_t) - { - return true; - } - bool link_list_erase(size_t, size_t) - { - return true; - } - bool link_list_nullify(size_t, size_t) - { - return true; - } - bool link_list_clear(size_t) - { - return true; - } - - void parse_complete() - { - } -}; -// LCOV_EXCL_STOP (NullInstructionObserver) - - -/// See TransactLogConvenientEncoder for information about the meaning of the -/// arguments of each of the functions in this class. -class TransactLogEncoder { -public: - /// The following methods are also those that TransactLogParser expects - /// to find on the `InstructionHandler`. - - // No selection needed: - bool select_table(size_t group_level_ndx, size_t levels, const size_t* path); - bool select_descriptor(size_t levels, const size_t* path); - bool select_link_list(size_t col_ndx, size_t row_ndx, size_t link_target_group_level_ndx); - bool insert_group_level_table(size_t table_ndx, size_t num_tables, StringData name); - bool erase_group_level_table(size_t table_ndx, size_t num_tables); - bool rename_group_level_table(size_t table_ndx, StringData new_name); - bool move_group_level_table(size_t from_table_ndx, size_t to_table_ndx); - - /// Must have table selected. - bool insert_empty_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool unordered); - bool erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool unordered); - bool swap_rows(size_t row_ndx_1, size_t row_ndx_2); - bool merge_rows(size_t row_ndx, size_t new_row_ndx); - bool clear_table(); - - bool set_int(size_t col_ndx, size_t row_ndx, int_fast64_t, Instruction = instr_Set, size_t = 0); - bool add_int(size_t col_ndx, size_t row_ndx, int_fast64_t); - bool set_bool(size_t col_ndx, size_t row_ndx, bool, Instruction = instr_Set); - bool set_float(size_t col_ndx, size_t row_ndx, float, Instruction = instr_Set); - bool set_double(size_t col_ndx, size_t row_ndx, double, Instruction = instr_Set); - bool set_string(size_t col_ndx, size_t row_ndx, StringData, Instruction = instr_Set, size_t = 0); - bool set_binary(size_t col_ndx, size_t row_ndx, BinaryData, Instruction = instr_Set); - bool set_olddatetime(size_t col_ndx, size_t row_ndx, OldDateTime, Instruction = instr_Set); - bool set_timestamp(size_t col_ndx, size_t row_ndx, Timestamp, Instruction = instr_Set); - bool set_table(size_t col_ndx, size_t row_ndx, Instruction = instr_Set); - bool set_mixed(size_t col_ndx, size_t row_ndx, const Mixed&, Instruction = instr_Set); - bool set_link(size_t col_ndx, size_t row_ndx, size_t, size_t target_group_level_ndx, Instruction = instr_Set); - bool set_null(size_t col_ndx, size_t row_ndx, Instruction = instr_Set, size_t = 0); - bool nullify_link(size_t col_ndx, size_t row_ndx, size_t target_group_level_ndx); - bool insert_substring(size_t col_ndx, size_t row_ndx, size_t pos, StringData); - bool erase_substring(size_t col_ndx, size_t row_ndx, size_t pos, size_t size); - bool optimize_table(); - - // Must have descriptor selected: - bool insert_link_column(size_t col_ndx, DataType, StringData name, size_t link_target_table_ndx, - size_t backlink_col_ndx); - bool insert_column(size_t col_ndx, DataType, StringData name, bool nullable = false); - bool erase_link_column(size_t col_ndx, size_t link_target_table_ndx, size_t backlink_col_ndx); - bool erase_column(size_t col_ndx); - bool rename_column(size_t col_ndx, StringData new_name); - bool move_column(size_t col_ndx_1, size_t col_ndx_2); - bool add_search_index(size_t col_ndx); - bool remove_search_index(size_t col_ndx); - bool set_link_type(size_t col_ndx, LinkType); - - // Must have linklist selected: - bool link_list_set(size_t link_ndx, size_t value, size_t prior_size); - bool link_list_set_all(const IntegerColumn& values); - bool link_list_insert(size_t link_ndx, size_t value, size_t prior_size); - bool link_list_move(size_t from_link_ndx, size_t to_link_ndx); - bool link_list_swap(size_t link1_ndx, size_t link2_ndx); - bool link_list_erase(size_t link_ndx, size_t prior_size); - bool link_list_nullify(size_t link_ndx, size_t prior_size); - bool link_list_clear(size_t old_list_size); - - /// End of methods expected by parser. - - - TransactLogEncoder(TransactLogStream& out_stream); - void set_buffer(char* new_free_begin, char* new_free_end); - char* write_position() const - { - return m_transact_log_free_begin; - } - -private: - // Make sure this is in agreement with the actual integer encoding - // scheme (see encode_int()). - static const int max_enc_bytes_per_int = 10; - static const int max_enc_bytes_per_double = sizeof(double); - static const int max_enc_bytes_per_num = - max_enc_bytes_per_int < max_enc_bytes_per_double ? max_enc_bytes_per_double : max_enc_bytes_per_int; - - // This value is used in Set* instructions in place of the 'type' field in - // the stream to indicate that the value of the Set* instruction is NULL, - // which doesn't have a type. - static constexpr int set_null_sentinel() - { - return -1; - } - - TransactLogStream& m_stream; - - // These two delimit a contiguous region of free space in a - // transaction log buffer following the last written data. It may - // be empty. - char* m_transact_log_free_begin = nullptr; - char* m_transact_log_free_end = nullptr; - - char* reserve(size_t size); - /// \param ptr Must be in the range [m_transact_log_free_begin, m_transact_log_free_end] - void advance(char* ptr) noexcept; - - template - void append_simple_instr(Instruction, const util::Tuple& numbers); - - template - void append_string_instr(Instruction, const util::Tuple& numbers, StringData); - - template - void append_mixed_instr(Instruction, const util::Tuple& numbers, const Mixed&); - - template - bool append_variable_size_instr(Instruction instr, const util::Tuple& numbers, I var_begin, I var_end); - - template - static char* encode_int(char*, T value); - static char* encode_bool(char*, bool value); - static char* encode_float(char*, float value); - static char* encode_double(char*, double value); - template - struct EncodeNumber; - friend class TransactLogParser; -}; - -class TransactLogConvenientEncoder { -public: - void insert_group_level_table(size_t table_ndx, size_t num_tables, StringData name); - void erase_group_level_table(size_t table_ndx, size_t num_tables); - void rename_group_level_table(size_t table_ndx, StringData new_name); - void move_group_level_table(size_t from_table_ndx, size_t to_table_ndx); - void insert_column(const Descriptor&, size_t col_ndx, DataType type, StringData name, LinkTargetInfo& link, - bool nullable = false); - void erase_column(const Descriptor&, size_t col_ndx); - void rename_column(const Descriptor&, size_t col_ndx, StringData name); - void move_column(const Descriptor&, size_t from, size_t to); - - void set_int(const Table*, size_t col_ndx, size_t ndx, int_fast64_t value, Instruction variant = instr_Set); - void add_int(const Table*, size_t col_ndx, size_t ndx, int_fast64_t value); - void set_bool(const Table*, size_t col_ndx, size_t ndx, bool value, Instruction variant = instr_Set); - void set_float(const Table*, size_t col_ndx, size_t ndx, float value, Instruction variant = instr_Set); - void set_double(const Table*, size_t col_ndx, size_t ndx, double value, Instruction variant = instr_Set); - void set_string(const Table*, size_t col_ndx, size_t ndx, StringData value, Instruction variant = instr_Set); - void set_binary(const Table*, size_t col_ndx, size_t ndx, BinaryData value, Instruction variant = instr_Set); - void set_olddatetime(const Table*, size_t col_ndx, size_t ndx, OldDateTime value, - Instruction variant = instr_Set); - void set_timestamp(const Table*, size_t col_ndx, size_t ndx, Timestamp value, Instruction variant = instr_Set); - void set_table(const Table*, size_t col_ndx, size_t ndx, Instruction variant = instr_Set); - void set_mixed(const Table*, size_t col_ndx, size_t ndx, const Mixed& value, Instruction variant = instr_Set); - void set_link(const Table*, size_t col_ndx, size_t ndx, size_t value, Instruction variant = instr_Set); - void set_null(const Table*, size_t col_ndx, size_t ndx, Instruction variant = instr_Set); - void set_link_list(const LinkView&, const IntegerColumn& values); - void insert_substring(const Table*, size_t col_ndx, size_t row_ndx, size_t pos, StringData); - void erase_substring(const Table*, size_t col_ndx, size_t row_ndx, size_t pos, size_t size); - - /// \param prior_num_rows The number of rows in the table prior to the - /// modification. - void insert_empty_rows(const Table*, size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows); - - /// \param prior_num_rows The number of rows in the table prior to the - /// modification. - void erase_rows(const Table*, size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, - bool is_move_last_over); - - void swap_rows(const Table*, size_t row_ndx_1, size_t row_ndx_2); - void merge_rows(const Table*, size_t row_ndx, size_t new_row_ndx); - void add_search_index(const Table*, size_t col_ndx); - void remove_search_index(const Table*, size_t col_ndx); - void set_link_type(const Table*, size_t col_ndx, LinkType); - void clear_table(const Table*); - void optimize_table(const Table*); - - void link_list_set(const LinkView&, size_t link_ndx, size_t value); - void link_list_insert(const LinkView&, size_t link_ndx, size_t value); - void link_list_move(const LinkView&, size_t from_link_ndx, size_t to_link_ndx); - void link_list_swap(const LinkView&, size_t link_ndx_1, size_t link_ndx_2); - void link_list_erase(const LinkView&, size_t link_ndx); - void link_list_clear(const LinkView&); - - //@{ - - /// Implicit nullifications due to removal of target row. This is redundant - /// information from the point of view of replication, as the removal of the - /// target row will reproduce the implicit nullifications in the target - /// Realm anyway. The purpose of this instruction is to allow observers - /// (reactor pattern) to be explicitly notified about the implicit - /// nullifications. - - void nullify_link(const Table*, size_t col_ndx, size_t ndx); - void link_list_nullify(const LinkView&, size_t link_ndx); - - //@} - - void on_table_destroyed(const Table*) noexcept; - void on_spec_destroyed(const Spec*) noexcept; - void on_link_list_destroyed(const LinkView&) noexcept; - -protected: - TransactLogConvenientEncoder(TransactLogStream& encoder); - - void reset_selection_caches() noexcept; - void set_buffer(char* new_free_begin, char* new_free_end) - { - m_encoder.set_buffer(new_free_begin, new_free_end); - } - char* write_position() const - { - return m_encoder.write_position(); - } - -private: - TransactLogEncoder m_encoder; - // These are mutable because they are caches. - mutable util::Buffer m_subtab_path_buf; - mutable const Table* m_selected_table; - mutable const Spec* m_selected_spec; - // Has to be atomic to support concurrent reset when a linklist - // is unselected. This can happen on a different thread. In case - // of races, setting of a new value must win. - mutable std::atomic m_selected_link_list; - - void unselect_all() noexcept; - void select_table(const Table*); // unselects descriptor and link list - void select_desc(const Descriptor&); // unselects link list - void select_link_list(const LinkView&); // unselects descriptor - - void record_subtable_path(const Table&, size_t*& out_begin, size_t*& out_end); - void do_select_table(const Table*); - void do_select_desc(const Descriptor&); - void do_select_link_list(const LinkView&); - - friend class TransactReverser; -}; - - -class TransactLogParser { -public: - class BadTransactLog; // Exception - - TransactLogParser(); - ~TransactLogParser() noexcept; - - /// See `TransactLogEncoder` for a list of methods that the `InstructionHandler` must define. - /// parse() promises that the path passed by reference to - /// InstructionHandler::select_descriptor() will remain valid - /// during subsequent calls to all descriptor modifying functions. - template - void parse(InputStream&, InstructionHandler&); - - template - void parse(NoCopyInputStream&, InstructionHandler&); - -private: - util::Buffer m_input_buffer; - - // The input stream is assumed to consist of chunks of memory organised such that - // every instruction resides in a single chunk only. - NoCopyInputStream* m_input; - // pointer into transaction log, each instruction is parsed from m_input_begin and onwards. - // Each instruction are assumed to be contiguous in memory. - const char* m_input_begin; - // pointer to one past current instruction log chunk. If m_input_begin reaches m_input_end, - // a call to next_input_buffer will move m_input_begin and m_input_end to a new chunk of - // memory. Setting m_input_end to 0 disables this check, and is used if it is already known - // that all of the instructions are in memory. - const char* m_input_end; - util::StringBuffer m_string_buffer; - static const int m_max_levels = 1024; - util::Buffer m_path; - - REALM_NORETURN void parser_error() const; - - template - void parse_one(InstructionHandler&); - bool has_next() noexcept; - - template - T read_int(); - - void read_bytes(char* data, size_t size); - BinaryData read_buffer(util::StringBuffer&, size_t size); - - bool read_bool(); - float read_float(); - double read_double(); - - StringData read_string(util::StringBuffer&); - BinaryData read_binary(util::StringBuffer&); - Timestamp read_timestamp(); - void read_mixed(Mixed*); - - // Advance m_input_begin and m_input_end to reflect the next block of instructions - // Returns false if no more input was available - bool next_input_buffer(); - - // return true if input was available - bool read_char(char&); // throws - - bool is_valid_data_type(int type); - bool is_valid_link_type(int type); -}; - - -class TransactLogParser::BadTransactLog : public std::exception { -public: - const char* what() const noexcept override - { - return "Bad transaction log"; - } -}; - - -/// Implementation: - -inline void TransactLogBufferStream::transact_log_reserve(size_t n, char** inout_new_begin, char** out_new_end) -{ - char* data = m_buffer.data(); - REALM_ASSERT(*inout_new_begin >= data); - REALM_ASSERT(*inout_new_begin <= (data + m_buffer.size())); - size_t size = *inout_new_begin - data; - m_buffer.reserve_extra(size, n); - data = m_buffer.data(); // May have changed - *inout_new_begin = data + size; - *out_new_end = data + m_buffer.size(); -} - -inline void TransactLogBufferStream::transact_log_append(const char* data, size_t size, char** out_new_begin, - char** out_new_end) -{ - transact_log_reserve(size, out_new_begin, out_new_end); - *out_new_begin = std::copy(data, data + size, *out_new_begin); -} - -inline const char* TransactLogBufferStream::transact_log_data() const -{ - return m_buffer.data(); -} - -inline TransactLogEncoder::TransactLogEncoder(TransactLogStream& stream) - : m_stream(stream) -{ -} - -inline void TransactLogEncoder::set_buffer(char* free_begin, char* free_end) -{ - REALM_ASSERT(free_begin <= free_end); - m_transact_log_free_begin = free_begin; - m_transact_log_free_end = free_end; -} - -inline void TransactLogConvenientEncoder::reset_selection_caches() noexcept -{ - unselect_all(); -} - -inline char* TransactLogEncoder::reserve(size_t n) -{ - if (size_t(m_transact_log_free_end - m_transact_log_free_begin) < n) { - m_stream.transact_log_reserve(n, &m_transact_log_free_begin, &m_transact_log_free_end); - } - return m_transact_log_free_begin; -} - -inline void TransactLogEncoder::advance(char* ptr) noexcept -{ - REALM_ASSERT_DEBUG(m_transact_log_free_begin <= ptr); - REALM_ASSERT_DEBUG(ptr <= m_transact_log_free_end); - m_transact_log_free_begin = ptr; -} - - -// The integer encoding is platform independent. Also, it does not -// depend on the type of the specified integer. Integers of any type -// can be encoded as long as the specified buffer is large enough (see -// below). The decoding does not have to use the same type. Decoding -// will fail if, and only if the encoded value falls outside the range -// of the requested destination type. -// -// The encoding uses one or more bytes. It never uses more than 8 bits -// per byte. The last byte in the sequence is the first one that has -// its 8th bit set to zero. -// -// Consider a particular non-negative value V. Let W be the number of -// bits needed to encode V using the trivial binary encoding of -// integers. The total number of bytes produced is then -// ceil((W+1)/7). The first byte holds the 7 least significant bits of -// V. The last byte holds at most 6 bits of V including the most -// significant one. The value of the first bit of the last byte is -// always 2**((N-1)*7) where N is the total number of bytes. -// -// A negative value W is encoded by setting the sign bit to one and -// then encoding the positive result of -(W+1) as described above. The -// advantage of this representation is that it converts small negative -// values to small positive values which require a small number of -// bytes. This would not have been true for 2's complements -// representation, for example. The sign bit is always stored as the -// 7th bit of the last byte. -// -// value bits value + sign max bytes -// -------------------------------------------------- -// int8_t 7 8 2 -// uint8_t 8 9 2 -// int16_t 15 16 3 -// uint16_t 16 17 3 -// int32_t 31 32 5 -// uint32_t 32 33 5 -// int64_t 63 64 10 -// uint64_t 64 65 10 -// -template -char* TransactLogEncoder::encode_int(char* ptr, T value) -{ - static_assert(std::numeric_limits::is_integer, "Integer required"); - bool negative = util::is_negative(value); - if (negative) { - // The following conversion is guaranteed by C++11 to never - // overflow (contrast this with "-value" which indeed could - // overflow). See C99+TC3 section 6.2.6.2 paragraph 2. - REALM_DIAG_PUSH(); - REALM_DIAG_IGNORE_UNSIGNED_MINUS(); - value = -(value + 1); - REALM_DIAG_POP(); - } - // At this point 'value' is always a positive number. Also, small - // negative numbers have been converted to small positive numbers. - REALM_ASSERT(!util::is_negative(value)); - // One sign bit plus number of value bits - const int num_bits = 1 + std::numeric_limits::digits; - // Only the first 7 bits are available per byte. Had it not been - // for the fact that maximum guaranteed bit width of a char is 8, - // this value could have been increased to 15 (one less than the - // number of value bits in 'unsigned'). - const int bits_per_byte = 7; - const int max_bytes = (num_bits + (bits_per_byte - 1)) / bits_per_byte; - static_assert(max_bytes <= max_enc_bytes_per_int, "Bad max_enc_bytes_per_int"); - // An explicit constant maximum number of iterations is specified - // in the hope that it will help the optimizer (to do loop - // unrolling, for example). - typedef unsigned char uchar; - for (int i = 0; i < max_bytes; ++i) { - if (value >> (bits_per_byte - 1) == 0) - break; - *reinterpret_cast(ptr) = uchar((1U << bits_per_byte) | unsigned(value & ((1U << bits_per_byte) - 1))); - ++ptr; - value >>= bits_per_byte; - } - *reinterpret_cast(ptr) = uchar(negative ? (1U << (bits_per_byte - 1)) | unsigned(value) : value); - return ++ptr; -} - -inline char* TransactLogEncoder::encode_bool(char* ptr, bool value) -{ - // A `char` is the smallest element that the encoder/decoder can process. So we encode the bool - // in a char. If we called encode_int it would end up as a char too, but we would get - // Various warnings about arithmetic on non-arithmetic type. - return encode_int(ptr, value); -} - -inline char* TransactLogEncoder::encode_float(char* ptr, float value) -{ - static_assert(std::numeric_limits::is_iec559 && - sizeof(float) * std::numeric_limits::digits == 32, - "Unsupported 'float' representation"); - const char* val_ptr = reinterpret_cast(&value); - return std::copy(val_ptr, val_ptr + sizeof value, ptr); -} - -inline char* TransactLogEncoder::encode_double(char* ptr, double value) -{ - static_assert(std::numeric_limits::is_iec559 && - sizeof(double) * std::numeric_limits::digits == 64, - "Unsupported 'double' representation"); - const char* val_ptr = reinterpret_cast(&value); - return std::copy(val_ptr, val_ptr + sizeof value, ptr); -} - -template -struct TransactLogEncoder::EncodeNumber { - void operator()(T value, char** ptr) - { - auto value_2 = value + 0; // Perform integral promotion - *ptr = encode_int(*ptr, value_2); - } -}; -template <> -struct TransactLogEncoder::EncodeNumber { - void operator()(char value, char** ptr) - { - // Write the char as-is without encoding. - **ptr = value; - ++(*ptr); - } -}; -template <> -struct TransactLogEncoder::EncodeNumber { - void operator()(bool value, char** ptr) - { - *ptr = encode_bool(*ptr, value); - } -}; -template <> -struct TransactLogEncoder::EncodeNumber { - void operator()(float value, char** ptr) - { - *ptr = encode_float(*ptr, value); - } -}; -template <> -struct TransactLogEncoder::EncodeNumber { - void operator()(double value, char** ptr) - { - *ptr = encode_double(*ptr, value); - } -}; -template <> -struct TransactLogEncoder::EncodeNumber { - void operator()(DataType type, char** ptr) - { - auto value_2 = type + 0; // Perform integral promotion - *ptr = encode_int(*ptr, value_2); - } -}; - -template -void TransactLogEncoder::append_simple_instr(Instruction instr, const util::Tuple& numbers) -{ - size_t num_numbers = util::TypeCount::value; - size_t max_required_bytes = 1 + max_enc_bytes_per_num * num_numbers; - char* ptr = reserve(max_required_bytes); // Throws - *ptr++ = char(instr); - util::for_each(numbers, &ptr); - advance(ptr); -} - -template -void TransactLogEncoder::append_string_instr(Instruction instr, const util::Tuple& numbers, StringData string) -{ - size_t num_numbers = util::TypeCount::value + 1; - size_t max_required_bytes = 1 + max_enc_bytes_per_num * num_numbers + string.size(); - char* ptr = reserve(max_required_bytes); // Throws - *ptr++ = char(instr); - util::for_each(append(numbers, string.size()), &ptr); - ptr = std::copy(string.data(), string.data() + string.size(), ptr); - advance(ptr); -} - -template -void TransactLogEncoder::append_mixed_instr(Instruction instr, const util::Tuple& numbers, const Mixed& value) -{ - DataType type = value.get_type(); - auto numbers_2 = append(numbers, type); - switch (type) { - case type_Int: - append_simple_instr(instr, append(numbers_2, value.get_int())); // Throws - return; - case type_Bool: - append_simple_instr(instr, append(numbers_2, value.get_bool())); // Throws - return; - case type_Float: - append_simple_instr(instr, append(numbers_2, value.get_float())); // Throws - return; - case type_Double: - append_simple_instr(instr, append(numbers_2, value.get_double())); // Throws - return; - case type_OldDateTime: { - auto value_2 = value.get_olddatetime().get_olddatetime(); - append_simple_instr(instr, append(numbers_2, value_2)); // Throws - return; - } - case type_String: { - append_string_instr(instr, numbers_2, value.get_string()); // Throws - return; - } - case type_Binary: { - BinaryData value_2 = value.get_binary(); - StringData value_3(value_2.data(), value_2.size()); - append_string_instr(instr, numbers_2, value_3); // Throws - return; - } - case type_Timestamp: { - Timestamp ts = value.get_timestamp(); - int64_t seconds = ts.get_seconds(); - int32_t nano_seconds = ts.get_nanoseconds(); - auto numbers_3 = append(numbers_2, seconds); - append_simple_instr(instr, append(numbers_3, nano_seconds)); // Throws - return; - } - case type_Table: - append_simple_instr(instr, numbers_2); // Throws - return; - case type_Mixed: - // Mixed in mixed is not possible - REALM_ASSERT_RELEASE(false); - case type_Link: - case type_LinkList: - // FIXME: Need to handle new link types here. - REALM_ASSERT_RELEASE(false); - } - REALM_ASSERT_RELEASE(false); -} - -template -bool TransactLogEncoder::append_variable_size_instr(Instruction instr, const util::Tuple& numbers, I var_begin, - I var_end) -{ -// Space is reserved in chunks to avoid excessive over allocation. -#ifdef REALM_DEBUG - const int max_numbers_per_chunk = 2; // Increase the chance of chunking in debug mode -#else - const int max_numbers_per_chunk = 8; -#endif - size_t num_numbers = util::TypeCount::value + max_numbers_per_chunk; - size_t max_required_bytes = 1 + max_enc_bytes_per_num * num_numbers; - char* ptr = reserve(max_required_bytes); // Throws - *ptr++ = char(instr); - util::for_each(numbers, &ptr); - I i = var_begin; - while (var_end - i > max_numbers_per_chunk) { - for (int j = 0; j < max_numbers_per_chunk; ++j) - ptr = encode_int(ptr, *i++); - advance(ptr); - size_t max_required_bytes_2 = max_enc_bytes_per_num * max_numbers_per_chunk; - ptr = reserve(max_required_bytes_2); // Throws - } - while (i != var_end) - ptr = encode_int(ptr, *i++); - advance(ptr); - return true; -} - -inline void TransactLogConvenientEncoder::unselect_all() noexcept -{ - m_selected_table = nullptr; - m_selected_spec = nullptr; - // no race with on_link_list_destroyed since both are setting to nullptr - m_selected_link_list = nullptr; -} - -inline void TransactLogConvenientEncoder::select_table(const Table* table) -{ - if (table != m_selected_table) - do_select_table(table); // Throws - m_selected_spec = nullptr; - // no race with on_link_list_destroyed since both are setting to nullptr - m_selected_link_list = nullptr; -} - -inline void TransactLogConvenientEncoder::select_desc(const Descriptor& desc) -{ - typedef _impl::DescriptorFriend df; - if (&df::get_spec(desc) != m_selected_spec) - do_select_desc(desc); // Throws - // no race with on_link_list_destroyed since both are setting to nullptr - m_selected_link_list = nullptr; -} - -inline void TransactLogConvenientEncoder::select_link_list(const LinkView& list) -{ - // A race between this and a call to on_link_list_destroyed() must - // end up with m_selected_link_list pointing to the list argument given - // here. We assume that the list given to on_link_list_destroyed() can - // *never* be the same as the list argument given here. We resolve the - // race by a) always updating m_selected_link_list in do_select_link_list() - // and b) only atomically and conditionally updating it in - // on_link_list_destroyed(). - if (&list != m_selected_link_list) { - do_select_link_list(list); // Throws - } - m_selected_spec = nullptr; -} - - -inline bool TransactLogEncoder::insert_group_level_table(size_t table_ndx, size_t prior_num_tables, StringData name) -{ - append_string_instr(instr_InsertGroupLevelTable, util::tuple(table_ndx, prior_num_tables), name); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::insert_group_level_table(size_t table_ndx, size_t prior_num_tables, - StringData name) -{ - unselect_all(); - m_encoder.insert_group_level_table(table_ndx, prior_num_tables, name); // Throws -} - -inline bool TransactLogEncoder::erase_group_level_table(size_t table_ndx, size_t prior_num_tables) -{ - append_simple_instr(instr_EraseGroupLevelTable, util::tuple(table_ndx, prior_num_tables)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::erase_group_level_table(size_t table_ndx, size_t prior_num_tables) -{ - unselect_all(); - m_encoder.erase_group_level_table(table_ndx, prior_num_tables); // Throws -} - -inline bool TransactLogEncoder::rename_group_level_table(size_t table_ndx, StringData new_name) -{ - append_string_instr(instr_RenameGroupLevelTable, util::tuple(table_ndx), new_name); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::rename_group_level_table(size_t table_ndx, StringData new_name) -{ - unselect_all(); - m_encoder.rename_group_level_table(table_ndx, new_name); // Throws -} - -inline bool TransactLogEncoder::move_group_level_table(size_t from_table_ndx, size_t to_table_ndx) -{ - REALM_ASSERT(from_table_ndx != to_table_ndx); - append_simple_instr(instr_MoveGroupLevelTable, util::tuple(from_table_ndx, to_table_ndx)); - return true; -} - -inline void TransactLogConvenientEncoder::move_group_level_table(size_t from_table_ndx, size_t to_table_ndx) -{ - unselect_all(); - m_encoder.move_group_level_table(from_table_ndx, to_table_ndx); -} - -inline bool TransactLogEncoder::insert_column(size_t col_ndx, DataType type, StringData name, bool nullable) -{ - Instruction instr = (nullable ? instr_InsertNullableColumn : instr_InsertColumn); - append_string_instr(instr, util::tuple(col_ndx, type), name); // Throws - return true; -} - -inline bool TransactLogEncoder::insert_link_column(size_t col_ndx, DataType type, StringData name, - size_t link_target_table_ndx, size_t backlink_col_ndx) -{ - REALM_ASSERT(_impl::TableFriend::is_link_type(ColumnType(type))); - append_string_instr(instr_InsertLinkColumn, util::tuple(col_ndx, type, link_target_table_ndx, backlink_col_ndx), - name); // Throws - return true; -} - - -inline void TransactLogConvenientEncoder::insert_column(const Descriptor& desc, size_t col_ndx, DataType type, - StringData name, LinkTargetInfo& link, bool nullable) -{ - select_desc(desc); // Throws - if (link.is_valid()) { - typedef _impl::TableFriend tf; - typedef _impl::DescriptorFriend df; - size_t target_table_ndx = link.m_target_table->get_index_in_group(); - const Table& origin_table = df::get_root_table(desc); - REALM_ASSERT(origin_table.is_group_level()); - const Spec& target_spec = tf::get_spec(*(link.m_target_table)); - size_t origin_table_ndx = origin_table.get_index_in_group(); - size_t backlink_col_ndx = target_spec.find_backlink_column(origin_table_ndx, col_ndx); - REALM_ASSERT_3(backlink_col_ndx, ==, link.m_backlink_col_ndx); - m_encoder.insert_link_column(col_ndx, type, name, target_table_ndx, backlink_col_ndx); // Throws - } - else { - m_encoder.insert_column(col_ndx, type, name, nullable); // Throws - } -} - -inline bool TransactLogEncoder::erase_column(size_t col_ndx) -{ - append_simple_instr(instr_EraseColumn, util::tuple(col_ndx)); // Throws - return true; -} - -inline bool TransactLogEncoder::erase_link_column(size_t col_ndx, size_t link_target_table_ndx, - size_t backlink_col_ndx) -{ - append_simple_instr(instr_EraseLinkColumn, util::tuple(col_ndx, link_target_table_ndx, - backlink_col_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::erase_column(const Descriptor& desc, size_t col_ndx) -{ - select_desc(desc); // Throws - - DataType type = desc.get_column_type(col_ndx); - typedef _impl::TableFriend tf; - if (!tf::is_link_type(ColumnType(type))) { - m_encoder.erase_column(col_ndx); // Throws - } - else { // it's a link column: - REALM_ASSERT(desc.is_root()); - typedef _impl::DescriptorFriend df; - const Table& origin_table = df::get_root_table(desc); - REALM_ASSERT(origin_table.is_group_level()); - const Table& target_table = *tf::get_link_target_table_accessor(origin_table, col_ndx); - size_t target_table_ndx = target_table.get_index_in_group(); - const Spec& target_spec = tf::get_spec(target_table); - size_t origin_table_ndx = origin_table.get_index_in_group(); - size_t backlink_col_ndx = target_spec.find_backlink_column(origin_table_ndx, col_ndx); - m_encoder.erase_link_column(col_ndx, target_table_ndx, backlink_col_ndx); // Throws - } -} - -inline bool TransactLogEncoder::rename_column(size_t col_ndx, StringData new_name) -{ - append_string_instr(instr_RenameColumn, util::tuple(col_ndx), new_name); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::rename_column(const Descriptor& desc, size_t col_ndx, StringData name) -{ - select_desc(desc); // Throws - m_encoder.rename_column(col_ndx, name); // Throws -} - - -inline bool TransactLogEncoder::move_column(size_t from, size_t to) -{ - append_simple_instr(instr_MoveColumn, util::tuple(from, to)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::move_column(const Descriptor& desc, size_t from, size_t to) -{ - select_desc(desc); // Throws - m_encoder.move_column(from, to); -} - - -inline bool TransactLogEncoder::set_int(size_t col_ndx, size_t ndx, int_fast64_t value, Instruction variant, - size_t prior_num_rows) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault || variant == instr_SetUnique, variant); - if (REALM_UNLIKELY(variant == instr_SetUnique)) - append_simple_instr(variant, util::tuple(type_Int, col_ndx, ndx, prior_num_rows, value)); // Throws - else - append_simple_instr(variant, util::tuple(type_Int, col_ndx, ndx, value)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_int(const Table* t, size_t col_ndx, size_t ndx, int_fast64_t value, - Instruction variant) -{ - select_table(t); // Throws - size_t prior_num_rows = (variant == instr_SetUnique ? t->size() : 0); - m_encoder.set_int(col_ndx, ndx, value, variant, prior_num_rows); // Throws -} - - -inline bool TransactLogEncoder::add_int(size_t col_ndx, size_t ndx, int_fast64_t value) -{ - append_simple_instr(instr_AddInteger, util::tuple(col_ndx, ndx, value)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::add_int(const Table* t, size_t col_ndx, size_t ndx, int_fast64_t value) -{ - select_table(t); // Throws - m_encoder.add_int(col_ndx, ndx, value); -} - -inline bool TransactLogEncoder::set_bool(size_t col_ndx, size_t ndx, bool value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr(variant, util::tuple(type_Bool, col_ndx, ndx, value)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_bool(const Table* t, size_t col_ndx, size_t ndx, bool value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_bool(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_float(size_t col_ndx, size_t ndx, float value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr(variant, util::tuple(type_Float, col_ndx, ndx, value)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_float(const Table* t, size_t col_ndx, size_t ndx, float value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_float(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_double(size_t col_ndx, size_t ndx, double value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr(instr_Set, util::tuple(type_Double, col_ndx, ndx, value)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_double(const Table* t, size_t col_ndx, size_t ndx, double value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_double(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_string(size_t col_ndx, size_t ndx, StringData value, Instruction variant, - size_t prior_num_rows) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault || variant == instr_SetUnique, variant); - if (value.is_null()) { - set_null(col_ndx, ndx, variant, prior_num_rows); // Throws - } - else { - if (REALM_UNLIKELY(variant == instr_SetUnique)) - append_string_instr(variant, util::tuple(type_String, col_ndx, ndx, prior_num_rows), value); // Throws - else - append_string_instr(variant, util::tuple(type_String, col_ndx, ndx), value); // Throws - } - return true; -} - -inline void TransactLogConvenientEncoder::set_string(const Table* t, size_t col_ndx, size_t ndx, StringData value, - Instruction variant) -{ - select_table(t); // Throws - size_t prior_num_rows = (variant == instr_SetUnique ? t->size() : 0); - m_encoder.set_string(col_ndx, ndx, value, variant, prior_num_rows); // Throws -} - -inline bool TransactLogEncoder::set_binary(size_t col_ndx, size_t row_ndx, BinaryData value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - if (value.is_null()) { - set_null(col_ndx, row_ndx, variant); // Throws - } - else { - StringData value_2(value.data(), value.size()); - append_string_instr(variant, util::tuple(type_Binary, col_ndx, row_ndx), value_2); // Throws - } - return true; -} - -inline void TransactLogConvenientEncoder::set_binary(const Table* t, size_t col_ndx, size_t ndx, BinaryData value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_binary(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_olddatetime(size_t col_ndx, size_t ndx, OldDateTime value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr(variant, util::tuple(type_OldDateTime, col_ndx, ndx, value.get_olddatetime())); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_olddatetime(const Table* t, size_t col_ndx, size_t ndx, - OldDateTime value, Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_olddatetime(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_timestamp(size_t col_ndx, size_t ndx, Timestamp value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr( - variant, util::tuple(type_Timestamp, col_ndx, ndx, value.get_seconds(), value.get_nanoseconds())); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_timestamp(const Table* t, size_t col_ndx, size_t ndx, Timestamp value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_timestamp(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_table(size_t col_ndx, size_t ndx, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_simple_instr(variant, util::tuple(type_Table, col_ndx, ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_table(const Table* t, size_t col_ndx, size_t ndx, Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_table(col_ndx, ndx, variant); // Throws -} - -inline bool TransactLogEncoder::set_mixed(size_t col_ndx, size_t ndx, const Mixed& value, Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - append_mixed_instr(variant, util::tuple(type_Mixed, col_ndx, ndx), value); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_mixed(const Table* t, size_t col_ndx, size_t ndx, const Mixed& value, - Instruction variant) -{ - select_table(t); // Throws - m_encoder.set_mixed(col_ndx, ndx, value, variant); // Throws -} - -inline bool TransactLogEncoder::set_link(size_t col_ndx, size_t ndx, size_t value, size_t target_group_level_ndx, - Instruction variant) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault, variant); - // Map `realm::npos` to zero, and `n` to `n+1`, where `n` is a target row - // index. - size_t value_2 = size_t(1) + value; - append_simple_instr(variant, util::tuple(type_Link, col_ndx, ndx, value_2, target_group_level_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_link(const Table* t, size_t col_ndx, size_t ndx, size_t value, - Instruction variant) -{ - select_table(t); // Throws - size_t target_group_level_ndx = t->get_descriptor()->get_column_link_target(col_ndx); - m_encoder.set_link(col_ndx, ndx, value, target_group_level_ndx, variant); // Throws -} - -inline bool TransactLogEncoder::set_null(size_t col_ndx, size_t ndx, Instruction variant, size_t prior_num_rows) -{ - REALM_ASSERT_EX(variant == instr_Set || variant == instr_SetDefault || variant == instr_SetUnique, variant); - if (REALM_UNLIKELY(variant == instr_SetUnique)) { - append_simple_instr(variant, util::tuple(set_null_sentinel(), col_ndx, ndx, prior_num_rows)); // Throws - } - else { - append_simple_instr(variant, util::tuple(set_null_sentinel(), col_ndx, ndx)); // Throws - } - return true; -} - -inline void TransactLogConvenientEncoder::set_null(const Table* t, size_t col_ndx, size_t row_ndx, - Instruction variant) -{ - select_table(t); // Throws - size_t prior_num_rows = (variant == instr_SetUnique ? t->size() : 0); - m_encoder.set_null(col_ndx, row_ndx, variant, prior_num_rows); // Throws -} - -inline bool TransactLogEncoder::nullify_link(size_t col_ndx, size_t ndx, size_t target_group_level_ndx) -{ - append_simple_instr(instr_NullifyLink, util::tuple(col_ndx, ndx, target_group_level_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::nullify_link(const Table* t, size_t col_ndx, size_t ndx) -{ - select_table(t); // Throws - size_t target_group_level_ndx = t->get_descriptor()->get_column_link_target(col_ndx); - m_encoder.nullify_link(col_ndx, ndx, target_group_level_ndx); // Throws -} - -inline bool TransactLogEncoder::insert_substring(size_t col_ndx, size_t row_ndx, size_t pos, StringData value) -{ - append_string_instr(instr_InsertSubstring, util::tuple(col_ndx, row_ndx, pos), value); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::insert_substring(const Table* t, size_t col_ndx, size_t row_ndx, size_t pos, - StringData value) -{ - if (value.size() > 0) { - select_table(t); // Throws - m_encoder.insert_substring(col_ndx, row_ndx, pos, value); // Throws - } -} - -inline bool TransactLogEncoder::erase_substring(size_t col_ndx, size_t row_ndx, size_t pos, size_t size) -{ - append_simple_instr(instr_EraseFromString, util::tuple(col_ndx, row_ndx, pos, size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::erase_substring(const Table* t, size_t col_ndx, size_t row_ndx, size_t pos, - size_t size) -{ - if (size > 0) { - select_table(t); // Throws - m_encoder.erase_substring(col_ndx, row_ndx, pos, size); // Throws - } -} - -inline bool TransactLogEncoder::insert_empty_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, - bool unordered) -{ - append_simple_instr(instr_InsertEmptyRows, - util::tuple(row_ndx, num_rows_to_insert, prior_num_rows, unordered)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::insert_empty_rows(const Table* t, size_t row_ndx, size_t num_rows_to_insert, - size_t prior_num_rows) -{ - select_table(t); // Throws - bool unordered = false; - m_encoder.insert_empty_rows(row_ndx, num_rows_to_insert, prior_num_rows, unordered); // Throws -} - -inline bool TransactLogEncoder::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, - bool unordered) -{ - append_simple_instr(instr_EraseRows, util::tuple(row_ndx, num_rows_to_erase, prior_num_rows, - unordered)); // Throws - return true; -} - - -inline void TransactLogConvenientEncoder::erase_rows(const Table* t, size_t row_ndx, size_t num_rows_to_erase, - size_t prior_num_rows, bool is_move_last_over) -{ - select_table(t); // Throws - bool unordered = is_move_last_over; - m_encoder.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, unordered); // Throws -} - -inline bool TransactLogEncoder::swap_rows(size_t row_ndx_1, size_t row_ndx_2) -{ - append_simple_instr(instr_SwapRows, util::tuple(row_ndx_1, row_ndx_2)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::swap_rows(const Table* t, size_t row_ndx_1, size_t row_ndx_2) -{ - REALM_ASSERT(row_ndx_1 < row_ndx_2); - select_table(t); // Throws - m_encoder.swap_rows(row_ndx_1, row_ndx_2); -} - -inline bool TransactLogEncoder::merge_rows(size_t row_ndx, size_t new_row_ndx) -{ - append_simple_instr(instr_MergeRows, util::tuple(row_ndx, new_row_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::merge_rows(const Table* t, size_t row_ndx, size_t new_row_ndx) -{ - select_table(t); // Throws - m_encoder.merge_rows(row_ndx, new_row_ndx); -} - -inline bool TransactLogEncoder::add_search_index(size_t col_ndx) -{ - append_simple_instr(instr_AddSearchIndex, util::tuple(col_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::add_search_index(const Table* t, size_t col_ndx) -{ - select_table(t); // Throws - m_encoder.add_search_index(col_ndx); // Throws -} - - -inline bool TransactLogEncoder::remove_search_index(size_t col_ndx) -{ - append_simple_instr(instr_RemoveSearchIndex, util::tuple(col_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::remove_search_index(const Table* t, size_t col_ndx) -{ - select_table(t); // Throws - m_encoder.remove_search_index(col_ndx); // Throws -} - -inline bool TransactLogEncoder::set_link_type(size_t col_ndx, LinkType link_type) -{ - append_simple_instr(instr_SetLinkType, util::tuple(col_ndx, int(link_type))); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_link_type(const Table* t, size_t col_ndx, LinkType link_type) -{ - select_table(t); // Throws - m_encoder.set_link_type(col_ndx, link_type); // Throws -} - - -inline bool TransactLogEncoder::clear_table() -{ - append_simple_instr(instr_ClearTable, util::tuple()); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::clear_table(const Table* t) -{ - select_table(t); // Throws - m_encoder.clear_table(); // Throws -} - -inline bool TransactLogEncoder::optimize_table() -{ - append_simple_instr(instr_OptimizeTable, util::tuple()); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::optimize_table(const Table* t) -{ - select_table(t); // Throws - m_encoder.optimize_table(); // Throws -} - -inline bool TransactLogEncoder::link_list_set(size_t link_ndx, size_t value, size_t prior_size) -{ - append_simple_instr(instr_LinkListSet, util::tuple(link_ndx, value, prior_size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_set(const LinkView& list, size_t link_ndx, size_t value) -{ - select_link_list(list); // Throws - m_encoder.link_list_set(link_ndx, value, list.size()); // Throws -} - -inline bool TransactLogEncoder::link_list_nullify(size_t link_ndx, size_t prior_size) -{ - append_simple_instr(instr_LinkListNullify, util::tuple(link_ndx, prior_size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_nullify(const LinkView& list, size_t link_ndx) -{ - select_link_list(list); // Throws - size_t prior_size = list.size(); // Instruction is emitted before the fact. - m_encoder.link_list_nullify(link_ndx, prior_size); // Throws -} - -inline bool TransactLogEncoder::link_list_set_all(const IntegerColumn& values) -{ - struct iter { - iter(const IntegerColumn& iter_values, size_t ndx) - : m_values(&iter_values) - , m_ndx(ndx) - { - } - const IntegerColumn* m_values; - size_t m_ndx; - bool operator==(const iter& i) const - { - return m_ndx == i.m_ndx; - } - bool operator!=(const iter& i) const - { - return m_ndx != i.m_ndx; - } - size_t operator-(const iter& i) const - { - return m_ndx - i.m_ndx; - } - int_fast64_t operator*() const - { - return m_values->get(m_ndx); - } - iter& operator++() - { - ++m_ndx; - return *this; - } - iter operator++(int) - { - iter i = *this; - ++m_ndx; - return i; - } - }; - size_t num_values = values.size(); - append_variable_size_instr(instr_LinkListSetAll, util::tuple(num_values), iter(values, 0), - iter(values, num_values)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::set_link_list(const LinkView& list, const IntegerColumn& values) -{ - select_link_list(list); // Throws - m_encoder.link_list_set_all(values); // Throws -} - -inline bool TransactLogEncoder::link_list_insert(size_t link_ndx, size_t value, size_t prior_size) -{ - append_simple_instr(instr_LinkListInsert, util::tuple(link_ndx, value, prior_size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_insert(const LinkView& list, size_t link_ndx, size_t value) -{ - select_link_list(list); // Throws - size_t prior_size = list.size() - 1; // The instruction is emitted after the fact. - m_encoder.link_list_insert(link_ndx, value, prior_size); // Throws -} - -inline bool TransactLogEncoder::link_list_move(size_t from_link_ndx, size_t to_link_ndx) -{ - REALM_ASSERT(from_link_ndx != to_link_ndx); - append_simple_instr(instr_LinkListMove, util::tuple(from_link_ndx, to_link_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_move(const LinkView& list, size_t from_link_ndx, - size_t to_link_ndx) -{ - select_link_list(list); // Throws - m_encoder.link_list_move(from_link_ndx, to_link_ndx); // Throws -} - -inline bool TransactLogEncoder::link_list_swap(size_t link1_ndx, size_t link2_ndx) -{ - append_simple_instr(instr_LinkListSwap, util::tuple(link1_ndx, link2_ndx)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_swap(const LinkView& list, size_t link1_ndx, size_t link2_ndx) -{ - select_link_list(list); // Throws - m_encoder.link_list_swap(link1_ndx, link2_ndx); // Throws -} - -inline bool TransactLogEncoder::link_list_erase(size_t link_ndx, size_t prior_size) -{ - append_simple_instr(instr_LinkListErase, util::tuple(link_ndx, prior_size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::link_list_erase(const LinkView& list, size_t link_ndx) -{ - select_link_list(list); // Throws - size_t prior_size = list.size(); // The instruction is emitted before the fact. - m_encoder.link_list_erase(link_ndx, prior_size); // Throws -} - -inline bool TransactLogEncoder::link_list_clear(size_t old_list_size) -{ - append_simple_instr(instr_LinkListClear, util::tuple(old_list_size)); // Throws - return true; -} - -inline void TransactLogConvenientEncoder::on_table_destroyed(const Table* t) noexcept -{ - if (m_selected_table == t) - m_selected_table = nullptr; -} - -inline void TransactLogConvenientEncoder::on_spec_destroyed(const Spec* s) noexcept -{ - if (m_selected_spec == s) - m_selected_spec = nullptr; -} - - -inline void TransactLogConvenientEncoder::on_link_list_destroyed(const LinkView& list) noexcept -{ - const LinkView* lw_ptr = &list; - // atomically clear m_selected_link_list iff it already points to 'list': - // (lw_ptr will be modified if the swap fails, but we ignore that) - m_selected_link_list.compare_exchange_strong(lw_ptr, nullptr, std::memory_order_relaxed, - std::memory_order_relaxed); -} - - -inline TransactLogParser::TransactLogParser() - : m_input_buffer(1024) // Throws -{ -} - - -inline TransactLogParser::~TransactLogParser() noexcept -{ -} - - -template -void TransactLogParser::parse(NoCopyInputStream& in, InstructionHandler& handler) -{ - m_input = ∈ - m_input_begin = m_input_end = nullptr; - - while (has_next()) - parse_one(handler); // Throws -} - -template -void TransactLogParser::parse(InputStream& in, InstructionHandler& handler) -{ - NoCopyInputStreamAdaptor in_2(in, m_input_buffer.data(), m_input_buffer.size()); - parse(in_2, handler); // Throws -} - -inline bool TransactLogParser::has_next() noexcept -{ - return m_input_begin != m_input_end || next_input_buffer(); -} - -template -void TransactLogParser::parse_one(InstructionHandler& handler) -{ - char instr_ch; - if (!read_char(instr_ch)) - parser_error(); // Throws - // std::cerr << "parsing " << util::promote(instr) << " @ " << std::hex << long(m_input_begin) << std::dec << - // "\n"; - Instruction instr = Instruction(instr_ch); - switch (instr) { - case instr_SetDefault: - case instr_SetUnique: - case instr_Set: { - int type = read_int(); // Throws - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - size_t prior_num_rows = 0; - if (REALM_UNLIKELY(instr == instr_SetUnique)) - prior_num_rows = read_int(); // Throws - - if (type == TransactLogEncoder::set_null_sentinel()) { - // Special case for set_null - if (!handler.set_null(col_ndx, row_ndx, instr, prior_num_rows)) // Throws - parser_error(); - return; - } - - switch (DataType(type)) { - case type_Int: { - int_fast64_t value = read_int(); // Throws - if (!handler.set_int(col_ndx, row_ndx, value, instr, prior_num_rows)) // Throws - parser_error(); - return; - } - case type_Bool: { - bool value = read_bool(); // Throws - if (!handler.set_bool(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_Float: { - float value = read_float(); // Throws - if (!handler.set_float(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_Double: { - double value = read_double(); // Throws - if (!handler.set_double(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_String: { - StringData value = read_string(m_string_buffer); // Throws - if (!handler.set_string(col_ndx, row_ndx, value, instr, prior_num_rows)) // Throws - parser_error(); - return; - } - case type_Binary: { - BinaryData value = read_binary(m_string_buffer); // Throws - if (!handler.set_binary(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_OldDateTime: { - int_fast64_t value = read_int(); // Throws - if (!handler.set_olddatetime(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_Timestamp: { - int64_t seconds = read_int(); // Throws - int32_t nanoseconds = read_int(); // Throws - Timestamp value = Timestamp(seconds, nanoseconds); - if (!handler.set_timestamp(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_Table: { - if (!handler.set_table(col_ndx, row_ndx, instr)) // Throws - parser_error(); - return; - } - case type_Mixed: { - Mixed value; - read_mixed(&value); // Throws - if (!handler.set_mixed(col_ndx, row_ndx, value, instr)) // Throws - parser_error(); - return; - } - case type_Link: { - size_t value = read_int(); // Throws - // Map zero to realm::npos, and `n+1` to `n`, where `n` is a target row index. - size_t target_row_ndx = size_t(value - 1); - size_t target_group_level_ndx = read_int(); // Throws - if (!handler.set_link(col_ndx, row_ndx, target_row_ndx, target_group_level_ndx, instr)) // Throws - parser_error(); - return; - } - case type_LinkList: { - // Unsupported column type for Set. - parser_error(); - return; - } - } - parser_error(); - return; - } - case instr_AddInteger: { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - int_fast64_t value = read_int(); // Throws - if (!handler.add_int(col_ndx, row_ndx, value)) // Throws - parser_error(); - return; - } - case instr_NullifyLink: { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - size_t target_group_level_ndx = read_int(); // Throws - if (!handler.nullify_link(col_ndx, row_ndx, target_group_level_ndx)) // Throws - parser_error(); - return; - } - case instr_InsertSubstring: { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - size_t pos = read_int(); // Throws - StringData value = read_string(m_string_buffer); // Throws - if (!handler.insert_substring(col_ndx, row_ndx, pos, value)) // Throws - parser_error(); - return; - } - case instr_EraseFromString: { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - size_t pos = read_int(); // Throws - size_t size = read_int(); // Throws - if (!handler.erase_substring(col_ndx, row_ndx, pos, size)) // Throws - parser_error(); - return; - } - case instr_InsertEmptyRows: { - size_t row_ndx = read_int(); // Throws - size_t num_rows_to_insert = read_int(); // Throws - size_t prior_num_rows = read_int(); // Throws - bool unordered = read_bool(); // Throws - if (!handler.insert_empty_rows(row_ndx, num_rows_to_insert, prior_num_rows, unordered)) // Throws - parser_error(); - return; - } - case instr_EraseRows: { - size_t row_ndx = read_int(); // Throws - size_t num_rows_to_erase = read_int(); // Throws - size_t prior_num_rows = read_int(); // Throws - bool unordered = read_bool(); // Throws - if (!handler.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, unordered)) // Throws - parser_error(); - return; - } - case instr_SwapRows: { - size_t row_ndx_1 = read_int(); // Throws - size_t row_ndx_2 = read_int(); // Throws - if (!handler.swap_rows(row_ndx_1, row_ndx_2)) // Throws - parser_error(); - return; - } - case instr_MergeRows: { - size_t row_ndx = read_int(); // Throws - size_t new_row_ndx = read_int(); // Throws - if (!handler.merge_rows(row_ndx, new_row_ndx)) // Throws - parser_error(); - return; - } - case instr_SelectTable: { - int levels = read_int(); // Throws - if (levels < 0 || levels > m_max_levels) - parser_error(); - m_path.reserve(0, 2 * levels); // Throws - size_t* path = m_path.data(); - size_t group_level_ndx = read_int(); // Throws - for (int i = 0; i != levels; ++i) { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - path[2 * i + 0] = col_ndx; - path[2 * i + 1] = row_ndx; - } - if (!handler.select_table(group_level_ndx, levels, path)) // Throws - parser_error(); - return; - } - case instr_ClearTable: { - if (!handler.clear_table()) // Throws - parser_error(); - return; - } - case instr_LinkListSet: { - size_t link_ndx = read_int(); // Throws - size_t value = read_int(); // Throws - size_t prior_size = read_int(); // Throws - if (!handler.link_list_set(link_ndx, value, prior_size)) // Throws - parser_error(); - return; - } - case instr_LinkListSetAll: { - // todo, log that it's a SetAll we're doing - size_t size = read_int(); // Throws - for (size_t i = 0; i < size; i++) { - size_t link = read_int(); // Throws - if (!handler.link_list_set(i, link, size)) // Throws - parser_error(); - } - return; - } - case instr_LinkListInsert: { - size_t link_ndx = read_int(); // Throws - size_t value = read_int(); // Throws - size_t prior_size = read_int(); // Throws - if (!handler.link_list_insert(link_ndx, value, prior_size)) // Throws - parser_error(); - return; - } - case instr_LinkListMove: { - size_t from_link_ndx = read_int(); // Throws - size_t to_link_ndx = read_int(); // Throws - if (!handler.link_list_move(from_link_ndx, to_link_ndx)) // Throws - parser_error(); - return; - } - case instr_LinkListSwap: { - size_t link1_ndx = read_int(); // Throws - size_t link2_ndx = read_int(); // Throws - if (!handler.link_list_swap(link1_ndx, link2_ndx)) // Throws - parser_error(); - return; - } - case instr_LinkListErase: { - size_t link_ndx = read_int(); // Throws - size_t prior_size = read_int(); // Throws - if (!handler.link_list_erase(link_ndx, prior_size)) // Throws - parser_error(); - return; - } - case instr_LinkListNullify: { - size_t link_ndx = read_int(); // Throws - size_t prior_size = read_int(); // Throws - if (!handler.link_list_nullify(link_ndx, prior_size)) // Throws - parser_error(); - return; - } - case instr_LinkListClear: { - size_t old_list_size = read_int(); // Throws - if (!handler.link_list_clear(old_list_size)) // Throws - parser_error(); - return; - } - case instr_SelectLinkList: { - size_t col_ndx = read_int(); // Throws - size_t row_ndx = read_int(); // Throws - size_t target_group_level_ndx = read_int(); // Throws - if (!handler.select_link_list(col_ndx, row_ndx, target_group_level_ndx)) // Throws - parser_error(); - return; - } - case instr_AddSearchIndex: { - size_t col_ndx = read_int(); // Throws - if (!handler.add_search_index(col_ndx)) // Throws - parser_error(); - return; - } - case instr_RemoveSearchIndex: { - size_t col_ndx = read_int(); // Throws - if (!handler.remove_search_index(col_ndx)) // Throws - parser_error(); - return; - } - case instr_SetLinkType: { - size_t col_ndx = read_int(); // Throws - int link_type = read_int(); // Throws - if (!is_valid_link_type(link_type)) - parser_error(); - if (!handler.set_link_type(col_ndx, LinkType(link_type))) // Throws - parser_error(); - return; - } - case instr_InsertColumn: - case instr_InsertNullableColumn: { - size_t col_ndx = read_int(); // Throws - int type = read_int(); // Throws - if (!is_valid_data_type(type)) - parser_error(); - if (REALM_UNLIKELY(type == type_Link || type == type_LinkList)) - parser_error(); - StringData name = read_string(m_string_buffer); // Throws - bool nullable = (Instruction(instr) == instr_InsertNullableColumn); - if (REALM_UNLIKELY(nullable && (type == type_Table || type == type_Mixed))) { - // Nullability not supported for Table and Mixed columns. - parser_error(); - } - if (!handler.insert_column(col_ndx, DataType(type), name, nullable)) // Throws - parser_error(); - return; - } - case instr_InsertLinkColumn: { - size_t col_ndx = read_int(); // Throws - int type = read_int(); // Throws - if (!is_valid_data_type(type)) - parser_error(); - if (REALM_UNLIKELY(type != type_Link && type != type_LinkList)) - parser_error(); - size_t link_target_table_ndx = read_int(); // Throws - size_t backlink_col_ndx = read_int(); // Throws - StringData name = read_string(m_string_buffer); // Throws - if (!handler.insert_link_column(col_ndx, DataType(type), name, link_target_table_ndx, - backlink_col_ndx)) // Throws - parser_error(); - return; - } - case instr_EraseColumn: { - size_t col_ndx = read_int(); // Throws - if (!handler.erase_column(col_ndx)) // Throws - parser_error(); - return; - } - case instr_EraseLinkColumn: { - size_t col_ndx = read_int(); // Throws - size_t link_target_table_ndx = read_int(); // Throws - size_t backlink_col_ndx = read_int(); // Throws - if (!handler.erase_link_column(col_ndx, link_target_table_ndx, backlink_col_ndx)) // Throws - parser_error(); - return; - } - case instr_RenameColumn: { - size_t col_ndx = read_int(); // Throws - StringData name = read_string(m_string_buffer); // Throws - if (!handler.rename_column(col_ndx, name)) // Throws - parser_error(); - return; - } - case instr_MoveColumn: { - size_t col_ndx_1 = read_int(); // Throws - size_t col_ndx_2 = read_int(); // Throws - if (!handler.move_column(col_ndx_1, col_ndx_2)) // Throws - parser_error(); - return; - } - case instr_SelectDescriptor: { - int levels = read_int(); // Throws - if (levels < 0 || levels > m_max_levels) - parser_error(); - m_path.reserve(0, levels); // Throws - size_t* path = m_path.data(); - for (int i = 0; i != levels; ++i) { - size_t col_ndx = read_int(); // Throws - path[i] = col_ndx; - } - if (!handler.select_descriptor(levels, path)) // Throws - parser_error(); - return; - } - case instr_InsertGroupLevelTable: { - size_t table_ndx = read_int(); // Throws - size_t num_tables = read_int(); // Throws - StringData name = read_string(m_string_buffer); // Throws - if (!handler.insert_group_level_table(table_ndx, num_tables, name)) // Throws - parser_error(); - return; - } - case instr_EraseGroupLevelTable: { - size_t table_ndx = read_int(); // Throws - size_t prior_num_tables = read_int(); // Throws - if (!handler.erase_group_level_table(table_ndx, prior_num_tables)) // Throws - parser_error(); - return; - } - case instr_RenameGroupLevelTable: { - size_t table_ndx = read_int(); // Throws - StringData new_name = read_string(m_string_buffer); // Throws - if (!handler.rename_group_level_table(table_ndx, new_name)) // Throws - parser_error(); - return; - } - case instr_MoveGroupLevelTable: { - size_t from_table_ndx = read_int(); // Throws - size_t to_table_ndx = read_int(); // Throws - if (!handler.move_group_level_table(from_table_ndx, to_table_ndx)) // Throws - parser_error(); - return; - } - case instr_OptimizeTable: { - if (!handler.optimize_table()) // Throws - parser_error(); - return; - } - } - - throw BadTransactLog(); -} - - -template -T TransactLogParser::read_int() -{ - T value = 0; - int part = 0; - const int max_bytes = (std::numeric_limits::digits + 1 + 6) / 7; - for (int i = 0; i != max_bytes; ++i) { - char c; - if (!read_char(c)) - goto bad_transact_log; - part = static_cast(c); - if (0xFF < part) - goto bad_transact_log; // Only the first 8 bits may be used in each byte - if ((part & 0x80) == 0) { - T p = part & 0x3F; - if (util::int_shift_left_with_overflow_detect(p, i * 7)) - goto bad_transact_log; - value |= p; - break; - } - if (i == max_bytes - 1) - goto bad_transact_log; // Too many bytes - value |= T(part & 0x7F) << (i * 7); - } - if (part & 0x40) { - // The real value is negative. Because 'value' is positive at - // this point, the following negation is guaranteed by C++11 - // to never overflow. See C99+TC3 section 6.2.6.2 paragraph 2. - REALM_DIAG_PUSH(); - REALM_DIAG_IGNORE_UNSIGNED_MINUS(); - value = -value; - REALM_DIAG_POP(); - if (util::int_subtract_with_overflow_detect(value, 1)) - goto bad_transact_log; - } - return value; - -bad_transact_log: - throw BadTransactLog(); -} - - -inline void TransactLogParser::read_bytes(char* data, size_t size) -{ - for (;;) { - const size_t avail = m_input_end - m_input_begin; - if (size <= avail) - break; - const char* to = m_input_begin + avail; - std::copy(m_input_begin, to, data); - if (!next_input_buffer()) - throw BadTransactLog(); - data += avail; - size -= avail; - } - const char* to = m_input_begin + size; - std::copy(m_input_begin, to, data); - m_input_begin = to; -} - - -inline BinaryData TransactLogParser::read_buffer(util::StringBuffer& buf, size_t size) -{ - const size_t avail = m_input_end - m_input_begin; - if (avail >= size) { - m_input_begin += size; - return BinaryData(m_input_begin - size, size); - } - - buf.clear(); - buf.resize(size); // Throws - read_bytes(buf.data(), size); - return BinaryData(buf.data(), size); -} - - -inline bool TransactLogParser::read_bool() -{ - return read_int(); -} - - -inline float TransactLogParser::read_float() -{ - static_assert(std::numeric_limits::is_iec559 && - sizeof(float) * std::numeric_limits::digits == 32, - "Unsupported 'float' representation"); - float value; - read_bytes(reinterpret_cast(&value), sizeof value); // Throws - return value; -} - - -inline double TransactLogParser::read_double() -{ - static_assert(std::numeric_limits::is_iec559 && - sizeof(double) * std::numeric_limits::digits == 64, - "Unsupported 'double' representation"); - double value; - read_bytes(reinterpret_cast(&value), sizeof value); // Throws - return value; -} - - -inline StringData TransactLogParser::read_string(util::StringBuffer& buf) -{ - size_t size = read_int(); // Throws - - if (size > Table::max_string_size) - parser_error(); - - BinaryData buffer = read_buffer(buf, size); - return StringData{buffer.data(), size}; -} - -inline Timestamp TransactLogParser::read_timestamp() -{ - REALM_ASSERT(false); - return Timestamp{}; -} - - -inline BinaryData TransactLogParser::read_binary(util::StringBuffer& buf) -{ - size_t size = read_int(); // Throws - - if (size > ArrayBlob::max_binary_size) - parser_error(); - - return read_buffer(buf, size); -} - - -inline void TransactLogParser::read_mixed(Mixed* mixed) -{ - DataType type = DataType(read_int()); // Throws - switch (type) { - case type_Int: { - int_fast64_t value = read_int(); // Throws - mixed->set_int(value); - return; - } - case type_Bool: { - bool value = read_bool(); // Throws - mixed->set_bool(value); - return; - } - case type_Float: { - float value = read_float(); // Throws - mixed->set_float(value); - return; - } - case type_Double: { - double value = read_double(); // Throws - mixed->set_double(value); - return; - } - case type_OldDateTime: { - int_fast64_t value = read_int(); // Throws - mixed->set_olddatetime(value); - return; - } - case type_Timestamp: { - Timestamp value = read_timestamp(); // Throws - mixed->set_timestamp(value); - return; - } - case type_String: { - StringData value = read_string(m_string_buffer); // Throws - mixed->set_string(value); - return; - } - case type_Binary: { - BinaryData value = read_binary(m_string_buffer); // Throws - mixed->set_binary(value); - return; - } - case type_Table: { - *mixed = Mixed::subtable_tag(); - return; - } - case type_Mixed: - break; - case type_Link: - case type_LinkList: - // FIXME: Need to handle new link types here - break; - } - throw BadTransactLog(); -} - - -inline bool TransactLogParser::next_input_buffer() -{ - return m_input->next_block(m_input_begin, m_input_end); -} - - -inline bool TransactLogParser::read_char(char& c) -{ - if (m_input_begin == m_input_end && !next_input_buffer()) - return false; - c = *m_input_begin++; - return true; -} - - -inline bool TransactLogParser::is_valid_data_type(int type) -{ - switch (DataType(type)) { - case type_Int: - case type_Bool: - case type_Float: - case type_Double: - case type_String: - case type_Binary: - case type_OldDateTime: - case type_Timestamp: - case type_Table: - case type_Mixed: - case type_Link: - case type_LinkList: - return true; - } - return false; -} - - -inline bool TransactLogParser::is_valid_link_type(int type) -{ - switch (LinkType(type)) { - case link_Strong: - case link_Weak: - return true; - } - return false; -} - - -class TransactReverser { -public: - bool select_table(size_t group_level_ndx, size_t levels, const size_t* path) - { - sync_table(); - m_encoder.select_table(group_level_ndx, levels, path); - m_pending_ts_instr = get_inst(); - return true; - } - - bool select_descriptor(size_t levels, const size_t* path) - { - sync_descriptor(); - m_encoder.select_descriptor(levels, path); - m_pending_ds_instr = get_inst(); - return true; - } - - bool insert_group_level_table(size_t table_ndx, size_t num_tables, StringData) - { - sync_table(); - m_encoder.erase_group_level_table(table_ndx, num_tables + 1); - append_instruction(); - return true; - } - - bool erase_group_level_table(size_t table_ndx, size_t num_tables) - { - sync_table(); - m_encoder.insert_group_level_table(table_ndx, num_tables - 1, ""); - append_instruction(); - return true; - } - - bool rename_group_level_table(size_t, StringData) - { - sync_table(); - return true; - } - - bool move_group_level_table(size_t from_table_ndx, size_t to_table_ndx) - { - sync_table(); - m_encoder.move_group_level_table(to_table_ndx, from_table_ndx); - append_instruction(); - return true; - } - - bool optimize_table() - { - return true; // No-op - } - - bool insert_empty_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool unordered) - { - size_t num_rows_to_erase = num_rows_to_insert; - size_t prior_num_rows_2 = prior_num_rows + num_rows_to_insert; - m_encoder.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows_2, unordered); // Throws - append_instruction(); - return true; - } - - bool erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool unordered) - { - size_t num_rows_to_insert = num_rows_to_erase; - // Number of rows in table after removal, but before inverse insertion - size_t prior_num_rows_2 = prior_num_rows - num_rows_to_erase; - m_encoder.insert_empty_rows(row_ndx, num_rows_to_insert, prior_num_rows_2, unordered); // Throws - append_instruction(); - return true; - } - - bool swap_rows(size_t row_ndx_1, size_t row_ndx_2) - { - m_encoder.swap_rows(row_ndx_1, row_ndx_2); - append_instruction(); - return true; - } - - bool merge_rows(size_t row_ndx, size_t new_row_ndx) - { - static_cast(row_ndx); - static_cast(new_row_ndx); - // There is no instruction we can generate here to change back. - return true; - } - - bool set_int(size_t col_ndx, size_t row_ndx, int_fast64_t value, Instruction variant, size_t prior_num_rows) - { - m_encoder.set_int(col_ndx, row_ndx, value, variant, prior_num_rows); - append_instruction(); - return true; - } - - bool add_int(size_t col_ndx, size_t row_ndx, int_fast64_t value) - { - m_encoder.add_int(col_ndx, row_ndx, -value); - append_instruction(); - return true; - } - - bool set_bool(size_t col_ndx, size_t row_ndx, bool value, Instruction variant) - { - m_encoder.set_bool(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_float(size_t col_ndx, size_t row_ndx, float value, Instruction variant) - { - m_encoder.set_float(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_double(size_t col_ndx, size_t row_ndx, double value, Instruction variant) - { - m_encoder.set_double(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_string(size_t col_ndx, size_t row_ndx, StringData value, Instruction variant, size_t prior_num_rows) - { - m_encoder.set_string(col_ndx, row_ndx, value, variant, prior_num_rows); - append_instruction(); - return true; - } - - bool set_binary(size_t col_ndx, size_t row_ndx, BinaryData value, Instruction variant) - { - m_encoder.set_binary(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_olddatetime(size_t col_ndx, size_t row_ndx, OldDateTime value, Instruction variant) - { - m_encoder.set_olddatetime(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_timestamp(size_t col_ndx, size_t row_ndx, Timestamp value, Instruction variant) - { - m_encoder.set_timestamp(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_table(size_t col_ndx, size_t row_ndx, Instruction variant) - { - m_encoder.set_table(col_ndx, row_ndx, variant); - append_instruction(); - return true; - } - - bool set_mixed(size_t col_ndx, size_t row_ndx, const Mixed& value, Instruction variant) - { - m_encoder.set_mixed(col_ndx, row_ndx, value, variant); - append_instruction(); - return true; - } - - bool set_null(size_t col_ndx, size_t row_ndx, Instruction variant, size_t prior_num_rows) - { - m_encoder.set_null(col_ndx, row_ndx, variant, prior_num_rows); - append_instruction(); - return true; - } - - bool set_link(size_t col_ndx, size_t row_ndx, size_t value, size_t target_group_level_ndx, Instruction variant) - { - m_encoder.set_link(col_ndx, row_ndx, value, target_group_level_ndx, variant); - append_instruction(); - return true; - } - - bool insert_substring(size_t, size_t, size_t, StringData) - { - return true; // No-op - } - - bool erase_substring(size_t, size_t, size_t, size_t) - { - return true; // No-op - } - - bool clear_table() - { - // FIXME: Add a comment on why we call insert_empty_rows() inside clear_table() - m_encoder.insert_empty_rows(0, 0, 0, true); - append_instruction(); - return true; - } - - bool add_search_index(size_t) - { - return true; // No-op - } - - bool remove_search_index(size_t) - { - return true; // No-op - } - - bool set_link_type(size_t, LinkType) - { - return true; // No-op - } - - bool insert_link_column(size_t col_idx, DataType, StringData, size_t target_table_idx, size_t backlink_col_ndx) - { - m_encoder.erase_link_column(col_idx, target_table_idx, backlink_col_ndx); - append_instruction(); - return true; - } - - bool erase_link_column(size_t col_idx, size_t target_table_idx, size_t backlink_col_idx) - { - DataType type = type_Link; // The real type of the column doesn't matter here, - // but the encoder asserts that it's actually a link type. - m_encoder.insert_link_column(col_idx, type, "", target_table_idx, backlink_col_idx); - append_instruction(); - return true; - } - - bool insert_column(size_t col_idx, DataType, StringData, bool) - { - m_encoder.erase_column(col_idx); - append_instruction(); - return true; - } - - bool erase_column(size_t col_idx) - { - m_encoder.insert_column(col_idx, DataType(), ""); - append_instruction(); - return true; - } - - bool rename_column(size_t, StringData) - { - return true; // No-op - } - - bool move_column(size_t col_ndx_1, size_t col_ndx_2) - { - m_encoder.move_column(col_ndx_2, col_ndx_1); - append_instruction(); - return true; - } - - bool select_link_list(size_t col_ndx, size_t row_ndx, size_t link_target_group_level_ndx) - { - sync_linkview(); - m_encoder.select_link_list(col_ndx, row_ndx, link_target_group_level_ndx); - m_pending_lv_instr = get_inst(); - return true; - } - - bool link_list_set(size_t row, size_t value, size_t prior_size) - { - m_encoder.link_list_set(row, value, prior_size); - append_instruction(); - return true; - } - - bool link_list_insert(size_t link_ndx, size_t, size_t prior_size) - { - m_encoder.link_list_erase(link_ndx, prior_size + 1); - append_instruction(); - return true; - } - - bool link_list_move(size_t from_link_ndx, size_t to_link_ndx) - { - m_encoder.link_list_move(from_link_ndx, to_link_ndx); - append_instruction(); - return true; - } - - bool link_list_swap(size_t link1_ndx, size_t link2_ndx) - { - m_encoder.link_list_swap(link1_ndx, link2_ndx); - append_instruction(); - return true; - } - - bool link_list_erase(size_t link_ndx, size_t prior_size) - { - m_encoder.link_list_insert(link_ndx, 0, prior_size - 1); - append_instruction(); - return true; - } - - bool link_list_clear(size_t old_list_size) - { - // Append in reverse order because the reversed log is itself applied - // in reverse, and this way it generates all back-insertions rather than - // all front-insertions - for (size_t i = old_list_size; i > 0; --i) { - m_encoder.link_list_insert(i - 1, 0, old_list_size - i); - append_instruction(); - } - return true; - } - - bool nullify_link(size_t col_ndx, size_t row_ndx, size_t target_group_level_ndx) - { - size_t value = 0; - // FIXME: Is zero this right value to pass here, or should - // TransactReverser::nullify_link() also have taken a - // `target_group_level_ndx` argument. - m_encoder.set_link(col_ndx, row_ndx, value, target_group_level_ndx); - append_instruction(); - return true; - } - - bool link_list_nullify(size_t link_ndx, size_t prior_size) - { - m_encoder.link_list_insert(link_ndx, 0, prior_size - 1); - append_instruction(); - return true; - } - -private: - _impl::TransactLogBufferStream m_buffer; - _impl::TransactLogEncoder m_encoder{m_buffer}; - struct Instr { - size_t begin; - size_t end; - }; - std::vector m_instructions; - size_t current_instr_start = 0; - Instr m_pending_ts_instr{0, 0}; - Instr m_pending_ds_instr{0, 0}; - Instr m_pending_lv_instr{0, 0}; - - Instr get_inst() - { - Instr instr; - instr.begin = current_instr_start; - current_instr_start = transact_log_size(); - instr.end = current_instr_start; - return instr; - } - - size_t transact_log_size() const - { - REALM_ASSERT_3(m_encoder.write_position(), >=, m_buffer.transact_log_data()); - return m_encoder.write_position() - m_buffer.transact_log_data(); - } - - void append_instruction() - { - m_instructions.push_back(get_inst()); - } - - void append_instruction(Instr instr) - { - m_instructions.push_back(instr); - } - - void sync_select(Instr& pending_instr) - { - if (pending_instr.begin != pending_instr.end) { - append_instruction(pending_instr); - pending_instr = {0, 0}; - } - } - - void sync_linkview() - { - sync_select(m_pending_lv_instr); - } - - void sync_descriptor() - { - sync_linkview(); - sync_select(m_pending_ds_instr); - } - - void sync_table() - { - sync_descriptor(); - sync_select(m_pending_ts_instr); - } - - friend class ReversedNoCopyInputStream; -}; - - -class ReversedNoCopyInputStream : public NoCopyInputStream { -public: - ReversedNoCopyInputStream(TransactReverser& reverser) - : m_instr_order(reverser.m_instructions) - { - // push any pending select_table or select_descriptor into the buffer - reverser.sync_table(); - - m_buffer = reverser.m_buffer.transact_log_data(); - m_current = m_instr_order.size(); - } - - bool next_block(const char*& begin, const char*& end) override - { - if (m_current != 0) { - m_current--; - begin = m_buffer + m_instr_order[m_current].begin; - end = m_buffer + m_instr_order[m_current].end; - return (end > begin); - } - return false; - } - -private: - const char* m_buffer; - std::vector& m_instr_order; - size_t m_current; -}; - -} // namespace _impl -} // namespace realm - -#endif // REALM_IMPL_TRANSACT_LOG_HPP diff --git a/Example/Pods/Realm/include/core/realm/importer.hpp b/Example/Pods/Realm/include/core/realm/importer.hpp deleted file mode 100644 index 9ef54dc..0000000 --- a/Example/Pods/Realm/include/core/realm/importer.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_IMPORTER_HPP -#define REALM_IMPORTER_HPP - -/* -Main method: import_csv(). Arguments: ---------------------------------------------------------------------------------------------------------------------- -empty_as_string_flag: - Imports a column that has occurences of empty strings as String type column. Else fields arec onverted to - false/0/0.0 - -type_detection_rows: - tells how many rows to read before analyzing data types (to see if numeric rows are really - numeric everywhere, and not strings that happen to just mostly contain numeric characters - - -This library supports: ---------------------------------------------------------------------------------------------------------------------- - * Auto detection of float vs. double, depending on number of significant digits - * Bool types can be case insensitive "true, false, 0, 1, yes, no" - * Newline inside data fields, plus auto detection of non-conforming non-quoted newlines (as in some IBM sample - files) - * Realm types String, Integer, Bool, Float and Double - * Auto detection of header and naming of Realm columns accordingly - * double-quoted and non-quoted fields, and these can be mixed arbitrarely - * double-quotes inside data field - * *nix + MacOSv9 + Windows line feed - * Scientific notation of floats/doubles (+1.23e-10) - * Comma in floats - but ONLY if field is double-quoted - * FAST FAST FAST (200 MB/s). Uses state-machine instead of traditional char-by-char loop with state checks inside - - -Problems: ---------------------------------------------------------------------------------------------------------------------- - A csv file does not tell its sheme. So we auto-detect it, based on the first N rows. However if a given column - contains 'false, false, false, hello' and we detect and create Realm table scheme using the first 3 rows, we fail - when we meet 'hello' (this error is handled with a thorough error message) - - Does not support commas in floats unless field is double-quoted - - -Design: ---------------------------------------------------------------------------------------------------------------------- - -import_csv(csv file handle, realm table) - Calls tokenize(csv file handle): - reads payload chunk and returns std::vector> with the right dimensions filled with - rows and columns of the chunk payload - Calls parse_float(), parse_bool(), etc, which tests for type and returns converted values - Calls table.add_empty_row(), table.set_float(), table.set_bool() -*/ - -#include - -// Disk read chunk size. This MUST be large enough to contain at least TWO rows of csv plaintext! It's a good idea -// to set it as low as ever possible (like 32 K) even though it's counter-intuitive with respect to performance. It -// will make the operating system read 32 K from disk and return it, and then read-ahead 32-64 K more after fread() -// has returned. This read-ahead behaviour does NOT occur if we request megabyte-sized chunks (observed on Windows 7 / -// Ubuntu) -static const size_t chunk_size = 32 * 1024; - -// Number of rows to csv-parse + insert into realm in each iteration. -static const size_t record_chunks = 100; - -// Width of each column when printing them on screen (non-Quiet mode) -const size_t print_width = 25; - -#include -#include - -namespace realm { - -class Importer { -public: - Importer(); - size_t import_csv_auto(FILE* file, Table& table, size_t type_detection_rows = 1000, - size_t import_rows = static_cast(-1)); - - size_t import_csv_manual(FILE* file, Table& table, std::vector scheme, - std::vector column_names, size_t skip_first_rows = 0, - size_t import_rows = static_cast(-1)); - - bool Quiet; // Quiet mode, only print to screen upon errors - char Separator; // csv delimitor/separator - bool Empty_as_string; // Import columns that have occurences of empty strings as String type column - -private: - size_t import_csv(FILE* file, Table& table, std::vector* import_scheme, - std::vector* column_names, size_t type_detection_rows, size_t skip_first_rows, - size_t import_rows); - template - float parse_float(const char* col, bool* success = nullptr); - template - double parse_double(const char* col, bool* success = nullptr, size_t* significants = nullptr); - template - int64_t parse_integer(const char* col, bool* success = nullptr); - template - bool parse_bool(const char* col, bool* success = nullptr); - std::vector types(std::vector v); - size_t tokenize(std::vector>& payload, size_t records); - std::vector detect_scheme(std::vector> payload, size_t begin, size_t end); - std::vector lowest_common(std::vector types1, std::vector types2); - - char src[2 * chunk_size]; // .csv input buffer - size_t m_top; // points at top of buffer - size_t m_curpos; // points at next byte to parse - FILE* m_file; // handle to .csv file - size_t m_fields; // number of fields in each row - size_t m_row; // current row in .csv file, including field-embedded line breaks. Used for err msg only -}; - -} // namespace realm - -#endif // REALM_IMPORTER_HPP diff --git a/Example/Pods/Realm/include/core/realm/index_string.hpp b/Example/Pods/Realm/include/core/realm/index_string.hpp deleted file mode 100644 index f215d67..0000000 --- a/Example/Pods/Realm/include/core/realm/index_string.hpp +++ /dev/null @@ -1,607 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_INDEX_STRING_HPP -#define REALM_INDEX_STRING_HPP - -#include -#include -#include - -#include -#include - -/* -The StringIndex class is used for both type_String and all integral types, such as type_Bool, type_OldDateTime and -type_Int. When used for integral types, the 64-bit integer is simply casted to a string of 8 bytes through a -pretty simple "wrapper layer" in all public methods. - -The StringIndex data structure is like an "inversed" B+ tree where the leafs contain row indexes and the non-leafs -contain 4-byte chunks of payload. Imagine a table with following strings: - - hello, kitty, kitten, foobar, kitty, foobar - -The topmost level of the index tree contains prefixes of the payload strings of length <= 4. The next level contains -prefixes of the remaining parts of the strings. Unnecessary levels of the tree are optimized away; the prefix "foob" -is shared only by rows that are identical ("foobar"), so "ar" is not needed to be stored in the tree. - - hell kitt foob - | /\ | - 0 en y {3, 5} - | \ - {1, 4} 2 - -Each non-leafs consists of two integer arrays of the same length, one containing payload and the other containing -references to the sublevel nodes. - -The leafs can be either a single value or a Column. If the reference in its parent node has its least significant -bit set, then the remaining upper bits specify the row index at which the string is stored. If the bit is clear, -it must be interpreted as a reference to a Column that stores the row indexes at which the string is stored. - -If a Column is used, then all row indexes are guaranteed to be sorted increasingly, which means you an search in it -using our binary search functions such as upper_bound() and lower_bound(). Each duplicate value will be stored in -the same Column, but Columns may contain more than just duplicates if the depth of the tree exceeds the value -`s_max_offset` This is to avoid stack overflow problems with many of our recursive functions if we have two very -long strings that have a long common prefix but differ in the last couple bytes. If a Column stores more than just -duplicates, then the list is kept sorted in ascending order by string value and within the groups of common -strings, the rows are sorted in ascending order. -*/ - -namespace realm { - -class Spec; -class Timestamp; - -class IndexArray : public Array { -public: - IndexArray(Allocator& allocator) - : Array(allocator) - { - } - - size_t index_string_find_first(StringData value, ColumnBase* column) const; - void index_string_find_all(IntegerColumn& result, StringData value, ColumnBase* column) const; - FindRes index_string_find_all_no_copy(StringData value, ColumnBase* column, InternalFindResult& result) const; - size_t index_string_count(StringData value, ColumnBase* column) const; - -private: - template - size_t from_list(StringData value, IntegerColumn& result, InternalFindResult& result_ref, - const IntegerColumn& rows, ColumnBase* column) const; - - template - size_t index_string(StringData value, IntegerColumn& result, InternalFindResult& result_ref, - ColumnBase* column) const; -}; - - -class StringIndex { -public: - StringIndex(ColumnBase* target_column, Allocator&); - StringIndex(ref_type, ArrayParent*, size_t ndx_in_parent, ColumnBase* target_column, bool allow_duplicate_values, - Allocator&); - ~StringIndex() noexcept - { - } - void set_target(ColumnBase* target_column) noexcept; - - // Accessor concept: - Allocator& get_alloc() const noexcept; - void destroy() noexcept; - void detach(); - bool is_attached() const noexcept; - void set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept; - size_t get_ndx_in_parent() const noexcept; - void set_ndx_in_parent(size_t ndx_in_parent) noexcept; - void update_from_parent(size_t old_baseline) noexcept; - void refresh_accessor_tree(size_t, const Spec&); - ref_type get_ref() const noexcept; - - // StringIndex interface: - - // 12 is the biggest element size of any non-string/binary Realm type - static const size_t string_conversion_buffer_size = 12; - using StringConversionBuffer = std::array; - - bool is_empty() const; - - template - void insert(size_t row_ndx, T value, size_t num_rows, bool is_append); - template - void insert(size_t row_ndx, util::Optional value, size_t num_rows, bool is_append); - - template - void set(size_t row_ndx, T new_value); - template - void set(size_t row_ndx, util::Optional new_value); - - template - void erase(size_t row_ndx, bool is_last); - - template - size_t find_first(T value) const; - template - void find_all(IntegerColumn& result, T value) const; - template - FindRes find_all_no_copy(T value, InternalFindResult& result) const; - template - size_t count(T value) const; - template - void update_ref(T value, size_t old_row_ndx, size_t new_row_ndx); - - void clear(); - - void distinct(IntegerColumn& result) const; - bool has_duplicate_values() const noexcept; - - /// By default, duplicate values are allowed. - void set_allow_duplicate_values(bool) noexcept; - - void verify() const; -#ifdef REALM_DEBUG - void verify_entries(const StringColumn& column) const; - void do_dump_node_structure(std::ostream&, int) const; - void to_dot() const; - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - - typedef int32_t key_type; - - // s_max_offset specifies the number of levels of recursive string indexes - // allowed before storing everything in lists. This is to avoid nesting - // to too deep of a level. Since every SubStringIndex stores 4 bytes, this - // means that a StringIndex is helpful for strings of a common prefix up to - // 4 times this limit (200 bytes shared). Lists are stored in sorted order, - // so strings sharing a common prefix of more than this limit will use a - // binary search of approximate complexity log2(n) from `std::lower_bound`. - static const size_t s_max_offset = 200; // max depth * s_index_key_length - static const size_t s_index_key_length = 4; - static key_type create_key(StringData) noexcept; - static key_type create_key(StringData, size_t) noexcept; - -private: - // m_array is a compact representation for storing the children of this StringIndex. - // Children can be: - // 1) a row number - // 2) a reference to a list which stores row numbers (for duplicate strings). - // 3) a reference to a sub-index - // m_array[0] is always a reference to a values array which stores the 4 byte chunk - // of payload data for quick string chunk comparisons. The array stored - // at m_array[0] lines up with the indices of values in m_array[1] so for example - // starting with an empty StringIndex: - // StringColumn::insert(target_row_ndx=42, value="test_string") would result with - // get_array_from_ref(m_array[0])[0] == create_key("test") and - // m_array[1] == 42 - // In this way, m_array which stores one child has a size of two. - // Children are type 1 (row number) if the LSB of the value is set. - // To get the actual row value, shift value down by one. - // If the LSB of the value is 0 then the value is a reference and can be either - // type 2, or type 3 (no shifting in either case). - // References point to a list if the context header flag is NOT set. - // If the header flag is set, references point to a sub-StringIndex (nesting). - std::unique_ptr m_array; - ColumnBase* m_target_column; - bool m_deny_duplicate_values; - - struct inner_node_tag { - }; - StringIndex(inner_node_tag, Allocator&); - - static IndexArray* create_node(Allocator&, bool is_leaf); - - void insert_with_offset(size_t row_ndx, StringData value, size_t offset); - void insert_row_list(size_t ref, size_t offset, StringData value); - void insert_to_existing_list(size_t row, StringData value, IntegerColumn& list); - void insert_to_existing_list_at_lower(size_t row, StringData value, IntegerColumn& list, - const IntegerColumnIterator& lower); - key_type get_last_key() const; - - /// Add small signed \a diff to all elements that are greater than, or equal - /// to \a min_row_ndx. - void adjust_row_indexes(size_t min_row_ndx, int diff); - - struct NodeChange { - size_t ref1; - size_t ref2; - enum ChangeType { none, insert_before, insert_after, split } type; - NodeChange(ChangeType t, size_t r1 = 0, size_t r2 = 0) - : ref1(r1) - , ref2(r2) - , type(t) - { - } - NodeChange() - : ref1(0) - , ref2(0) - , type(none) - { - } - }; - - // B-Tree functions - void TreeInsert(size_t row_ndx, key_type, size_t offset, StringData value); - NodeChange do_insert(size_t ndx, key_type, size_t offset, StringData value); - /// Returns true if there is room or it can join existing entries - bool leaf_insert(size_t row_ndx, key_type, size_t offset, StringData value, bool noextend = false); - void node_insert_split(size_t ndx, size_t new_ref); - void node_insert(size_t ndx, size_t ref); - void do_delete(size_t ndx, StringData, size_t offset); - void do_update_ref(StringData value, size_t row_ndx, size_t new_row_ndx, size_t offset); - - StringData get(size_t ndx, StringConversionBuffer& buffer) const; - - void node_add_key(ref_type ref); - -#ifdef REALM_DEBUG - static void dump_node_structure(const Array& node, std::ostream&, int level); - void to_dot_2(std::ostream&, StringData title = StringData()) const; - static void array_to_dot(std::ostream&, const Array&); - static void keys_to_dot(std::ostream&, const Array&, StringData title = StringData()); -#endif -}; - - -class SortedListComparator { -public: - SortedListComparator(ColumnBase& column_values); - bool operator()(int64_t ndx, StringData needle); - bool operator()(StringData needle, int64_t ndx); - -private: - ColumnBase& values; -}; - - -// Implementation: - -template -struct GetIndexData; - -template <> -struct GetIndexData { - static StringData get_index_data(const int64_t& value, StringIndex::StringConversionBuffer& buffer) - { - const char* c = reinterpret_cast(&value); - std::copy(c, c + sizeof(int64_t), buffer.data()); - return StringData{buffer.data(), sizeof(int64_t)}; - } -}; - -template <> -struct GetIndexData { - static StringData get_index_data(StringData data, StringIndex::StringConversionBuffer&) - { - return data; - } -}; - -template <> -struct GetIndexData { - static StringData get_index_data(null, StringIndex::StringConversionBuffer&) - { - return null{}; - } -}; - -template <> -struct GetIndexData { - static StringData get_index_data(const Timestamp&, StringIndex::StringConversionBuffer&); -}; - -template -struct GetIndexData> { - static StringData get_index_data(const util::Optional& value, StringIndex::StringConversionBuffer& buffer) - { - if (value) - return GetIndexData::get_index_data(*value, buffer); - return null{}; - } -}; - -template <> -struct GetIndexData { - static StringData get_index_data(float, StringIndex::StringConversionBuffer&) - { - REALM_ASSERT_RELEASE(false); // LCOV_EXCL_LINE; Index on float not supported - } -}; - -template <> -struct GetIndexData { - static StringData get_index_data(double, StringIndex::StringConversionBuffer&) - { - REALM_ASSERT_RELEASE(false); // LCOV_EXCL_LINE; Index on float not supported - } -}; - -template <> -struct GetIndexData : GetIndexData { -}; - -// to_str() is used by the integer index. The existing StringIndex is re-used for this -// by making IntegerColumn convert its integers to strings by calling to_str(). - -template -inline StringData to_str(T&& value, StringIndex::StringConversionBuffer& buffer) -{ - return GetIndexData::type>::get_index_data(value, buffer); -} - - -inline StringIndex::StringIndex(ColumnBase* target_column, Allocator& alloc) - : m_array(create_node(alloc, true)) // Throws - , m_target_column(target_column) - , m_deny_duplicate_values(false) -{ -} - -inline StringIndex::StringIndex(ref_type ref, ArrayParent* parent, size_t ndx_in_parent, ColumnBase* target_column, - bool deny_duplicate_values, Allocator& alloc) - : m_array(new IndexArray(alloc)) - , m_target_column(target_column) - , m_deny_duplicate_values(deny_duplicate_values) -{ - REALM_ASSERT_EX(Array::get_context_flag_from_header(alloc.translate(ref)), ref, size_t(alloc.translate(ref))); - m_array->init_from_ref(ref); - set_parent(parent, ndx_in_parent); -} - -inline StringIndex::StringIndex(inner_node_tag, Allocator& alloc) - : m_array(create_node(alloc, false)) // Throws - , m_target_column(nullptr) - , m_deny_duplicate_values(false) -{ -} - -inline void StringIndex::set_allow_duplicate_values(bool allow) noexcept -{ - m_deny_duplicate_values = !allow; -} - -// Byte order of the key is *reversed*, so that for the integer index, the least significant -// byte comes first, so that it fits little-endian machines. That way we can perform fast -// range-lookups and iterate in order, etc, as future features. This, however, makes the same -// features slower for string indexes. Todo, we should reverse the order conditionally, depending -// on the column type. -inline StringIndex::key_type StringIndex::create_key(StringData str) noexcept -{ - key_type key = 0; - - if (str.size() >= 4) - goto four; - if (str.size() < 2) { - if (str.size() == 0) - goto none; - goto one; - } - if (str.size() == 2) - goto two; - goto three; - -// Create 4 byte index key -// (encoded like this to allow literal comparisons -// independently of endianness) -four: - key |= (key_type(static_cast(str[3])) << 0); -three: - key |= (key_type(static_cast(str[2])) << 8); -two: - key |= (key_type(static_cast(str[1])) << 16); -one: - key |= (key_type(static_cast(str[0])) << 24); -none: - return key; -} - -// Index works as follows: All non-NULL values are stored as if they had appended an 'X' character at the end. So -// "foo" is stored as if it was "fooX", and "" (empty string) is stored as "X". And NULLs are stored as empty strings. -inline StringIndex::key_type StringIndex::create_key(StringData str, size_t offset) noexcept -{ - if (str.is_null()) - return 0; - - if (offset > str.size()) - return 0; - - // for very short strings - size_t tail = str.size() - offset; - if (tail <= sizeof(key_type) - 1) { - char buf[sizeof(key_type)]; - memset(buf, 0, sizeof(key_type)); - buf[tail] = 'X'; - memcpy(buf, str.data() + offset, tail); - return create_key(StringData(buf, tail + 1)); - } - // else fallback - return create_key(str.substr(offset)); -} - -template -void StringIndex::insert(size_t row_ndx, T value, size_t num_rows, bool is_append) -{ - REALM_ASSERT_3(row_ndx, !=, npos); - - // If the new row is inserted after the last row in the table, we don't need - // to adjust any row indexes. - if (!is_append) { - for (size_t i = 0; i < num_rows; ++i) { - size_t row_ndx_2 = row_ndx + i; - adjust_row_indexes(row_ndx_2, 1); // Throws - } - } - - StringConversionBuffer buffer; - - for (size_t i = 0; i < num_rows; ++i) { - size_t row_ndx_2 = row_ndx + i; - size_t offset = 0; // First key from beginning of string - insert_with_offset(row_ndx_2, to_str(value, buffer), offset); // Throws - } -} - -template -void StringIndex::insert(size_t row_ndx, util::Optional value, size_t num_rows, bool is_append) -{ - if (value) { - insert(row_ndx, *value, num_rows, is_append); - } - else { - insert(row_ndx, null{}, num_rows, is_append); - } -} - -template -void StringIndex::set(size_t row_ndx, T new_value) -{ - StringConversionBuffer buffer; - StringConversionBuffer buffer2; - StringData old_value = get(row_ndx, buffer); - StringData new_value2 = to_str(new_value, buffer2); - - // Note that insert_with_offset() throws UniqueConstraintViolation. - - if (REALM_LIKELY(new_value2 != old_value)) { - // We must erase this row first because erase uses find_first which - // might find the duplicate if we insert before erasing. - bool is_last = true; // To avoid updating refs - erase(row_ndx, is_last); // Throws - - size_t offset = 0; // First key from beginning of string - insert_with_offset(row_ndx, new_value2, offset); // Throws - } -} - -template -void StringIndex::set(size_t row_ndx, util::Optional new_value) -{ - if (new_value) { - set(row_ndx, *new_value); - } - else { - set(row_ndx, null{}); - } -} - -template -void StringIndex::erase(size_t row_ndx, bool is_last) -{ - StringConversionBuffer buffer; - StringData value = get(row_ndx, buffer); - - do_delete(row_ndx, value, 0); - - // Collapse top nodes with single item - while (m_array->is_inner_bptree_node()) { - REALM_ASSERT(m_array->size() > 1); // node cannot be empty - if (m_array->size() > 2) - break; - - ref_type ref = m_array->get_as_ref(1); - m_array->set(1, 1); // avoid destruction of the extracted ref - m_array->destroy_deep(); - m_array->init_from_ref(ref); - m_array->update_parent(); - } - - // If it is last item in column, we don't have to update refs - if (!is_last) - adjust_row_indexes(row_ndx, -1); -} - -template -size_t StringIndex::find_first(T value) const -{ - // Use direct access method - StringConversionBuffer buffer; - return m_array->index_string_find_first(to_str(value, buffer), m_target_column); -} - -template -void StringIndex::find_all(IntegerColumn& result, T value) const -{ - // Use direct access method - StringConversionBuffer buffer; - return m_array->index_string_find_all(result, to_str(value, buffer), m_target_column); -} - -template -FindRes StringIndex::find_all_no_copy(T value, InternalFindResult& result) const -{ - // Use direct access method - StringConversionBuffer buffer; - return m_array->index_string_find_all_no_copy(to_str(value, buffer), m_target_column, result); -} - -template -size_t StringIndex::count(T value) const -{ - // Use direct access method - StringConversionBuffer buffer; - return m_array->index_string_count(to_str(value, buffer), m_target_column); -} - -template -void StringIndex::update_ref(T value, size_t old_row_ndx, size_t new_row_ndx) -{ - StringConversionBuffer buffer; - do_update_ref(to_str(value, buffer), old_row_ndx, new_row_ndx, 0); -} - -inline void StringIndex::destroy() noexcept -{ - return m_array->destroy_deep(); -} - -inline bool StringIndex::is_attached() const noexcept -{ - return m_array->is_attached(); -} - -inline void StringIndex::refresh_accessor_tree(size_t, const Spec&) -{ - m_array->init_from_parent(); -} - -inline ref_type StringIndex::get_ref() const noexcept -{ - return m_array->get_ref(); -} - -inline void StringIndex::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept -{ - m_array->set_parent(parent, ndx_in_parent); -} - -inline size_t StringIndex::get_ndx_in_parent() const noexcept -{ - return m_array->get_ndx_in_parent(); -} - -inline void StringIndex::set_ndx_in_parent(size_t ndx_in_parent) noexcept -{ - m_array->set_ndx_in_parent(ndx_in_parent); -} - -inline void StringIndex::update_from_parent(size_t old_baseline) noexcept -{ - m_array->update_from_parent(old_baseline); -} - -} // namespace realm - -#endif // REALM_INDEX_STRING_HPP diff --git a/Example/Pods/Realm/include/core/realm/lang_bind_helper.hpp b/Example/Pods/Realm/include/core/realm/lang_bind_helper.hpp deleted file mode 100644 index 9e93c77..0000000 --- a/Example/Pods/Realm/include/core/realm/lang_bind_helper.hpp +++ /dev/null @@ -1,380 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_LANG_BIND_HELPER_HPP -#define REALM_LANG_BIND_HELPER_HPP - -#include - -#include -#include -#include -#include -#include - -#include - -namespace realm { - - -/// These functions are only to be used by language bindings to gain -/// access to certain memebers that are othewise private. -/// -/// \note Applications are not supposed to call any of these functions -/// directly. -/// -/// All of the get_subtable_ptr() functions bind the table accessor pointer -/// before it is returned (bind_table_ptr()). The caller is then responsible for -/// making the corresponding call to unbind_table_ptr(). -class LangBindHelper { -public: - /// Increment the reference counter of the specified table accessor. This is - /// done automatically by all of the functions in this class that return - /// table accessor pointers, but if the binding/application makes a copy of - /// such a pointer, and the copy needs to have an "independent life", then - /// the binding/application must bind that copy using this function. - static void bind_table_ptr(const Table*) noexcept; - - /// Decrement the reference counter of the specified table accessor. The - /// binding/application must call this function for every bound table - /// accessor pointer object, when that pointer object ends its life. - static void unbind_table_ptr(const Table*) noexcept; - - /// Construct a new freestanding table. The table accessor pointer is bound - /// by the callee before it is returned (bind_table_ptr()). - static Table* new_table(); - - /// Construct a new freestanding table as a copy of the specified one. The - /// table accessor pointer is bound by the callee before it is returned - /// (bind_table_ptr()). - static Table* copy_table(const Table&); - - //@{ - - /// These functions are like their namesakes in Group, but these bypass the - /// construction of a smart-pointer object (TableRef). The table accessor - /// pointer is bound by the callee before it is returned (bind_table_ptr()). - - static Table* get_table(Group&, size_t index_in_group); - static const Table* get_table(const Group&, size_t index_in_group); - - static Table* get_table(Group&, StringData name); - static const Table* get_table(const Group&, StringData name); - - static Table* add_table(Group&, StringData name, bool require_unique_name = true); - static Table* get_or_add_table(Group&, StringData name, bool* was_added = nullptr); - - //@} - - static Table* get_subtable_ptr(Table*, size_t column_ndx, size_t row_ndx); - static const Table* get_subtable_ptr(const Table*, size_t column_ndx, size_t row_ndx); - - // FIXME: This is an 'oddball', do we really need it? If we do, - // please provide a comment that explains why it is needed! - static Table* get_subtable_ptr_during_insert(Table*, size_t col_ndx, size_t row_ndx); - - static Table* get_subtable_ptr(TableView*, size_t column_ndx, size_t row_ndx); - static const Table* get_subtable_ptr(const TableView*, size_t column_ndx, size_t row_ndx); - static const Table* get_subtable_ptr(const ConstTableView*, size_t column_ndx, size_t row_ndx); - - /// Calls parent.set_mixed_subtable(col_ndx, row_ndx, &source). Note - /// that the source table must have a descriptor that is - /// compatible with the target subtable column. - static void set_mixed_subtable(Table& parent, size_t col_ndx, size_t row_ndx, const Table& source); - - static const LinkViewRef& get_linklist_ptr(Row&, size_t col_ndx); - static void unbind_linklist_ptr(const LinkViewRef&); - - using VersionID = SharedGroup::VersionID; - - /// \defgroup lang_bind_helper_transactions Continuous Transactions - /// - /// advance_read() is equivalent to terminating the current read transaction - /// (SharedGroup::end_read()), and initiating a new one - /// (SharedGroup::begin_read()), except that all subordinate accessors - /// (Table, Row, Descriptor) will remain attached to the underlying objects, - /// unless those objects were removed in the target snapshot. By default, - /// the read transaction is advanced to the latest available snapshot, but - /// see SharedGroup::begin_read() for information about \a version. - /// - /// promote_to_write() is equivalent to terminating the current read - /// transaction (SharedGroup::end_read()), and initiating a new write - /// transaction (SharedGroup::begin_write()), except that all subordinate - /// accessors (Table, Row, Descriptor) will remain attached to the - /// underlying objects, unless those objects were removed in the target - /// snapshot. - /// - /// commit_and_continue_as_read() is equivalent to committing the current - /// write transaction (SharedGroup::commit()) and initiating a new read - /// transaction, which is bound to the snapshot produced by the write - /// transaction (SharedGroup::begin_read()), except that all subordinate - /// accessors (Table, Row, Descriptor) will remain attached to the - /// underlying objects. commit_and_continue_as_read() returns the version - /// produced by the committed transaction. - /// - /// rollback_and_continue_as_read() is equivalent to rolling back the - /// current write transaction (SharedGroup::rollback()) and initiating a new - /// read transaction, which is bound to the snapshot, that the write - /// transaction was based on (SharedGroup::begin_read()), except that all - /// subordinate accessors (Table, Row, Descriptor) will remain attached to - /// the underlying objects, unless they were attached to object that were - /// added during the rolled back transaction. - /// - /// If advance_read(), promote_to_write(), commit_and_continue_as_read(), or - /// rollback_and_continue_as_read() throws, the associated group accessor - /// and all of its subordinate accessors are left in a state that may not be - /// fully consistent. Only minimal consistency is guaranteed (see - /// AccessorConsistencyLevels). In this case, the application is required to - /// either destroy the SharedGroup object, forcing all associated accessors - /// to become detached, or take some other equivalent action that involves a - /// complete accessor detachment, such as terminating the transaction in - /// progress. Until then it is an error, and unsafe if the application - /// attempts to access any of those accessors. - /// - /// The application must use SharedGroup::end_read() if it wants to - /// terminate the transaction after advance_read() or promote_to_write() has - /// thrown an exception. Likewise, it must use SharedGroup::rollback() if it - /// wants to terminate the transaction after commit_and_continue_as_read() - /// or rollback_and_continue_as_read() has thrown an exception. - /// - /// \param observer An optional custom replication instruction handler. The - /// application may pass such a handler to observe the sequence of - /// modifications that advances (or rolls back) the state of the Realm. - /// - /// \throw SharedGroup::BadVersion Thrown by advance_read() if the specified - /// version does not correspond to a bound (or tethered) snapshot. - /// - //@{ - - static void advance_read(SharedGroup&, VersionID = VersionID()); - template - static void advance_read(SharedGroup&, O&& observer, VersionID = VersionID()); - static void promote_to_write(SharedGroup&); - template - static void promote_to_write(SharedGroup&, O&& observer); - static SharedGroup::version_type commit_and_continue_as_read(SharedGroup&); - static void rollback_and_continue_as_read(SharedGroup&); - template - static void rollback_and_continue_as_read(SharedGroup&, O&& observer); - - //@} - - /// Returns the name of the specified data type. Examples: - /// - ///
-    ///
-    ///   type_Int          ->  "int"
-    ///   type_Bool         ->  "bool"
-    ///   type_Float        ->  "float"
-    ///   ...
-    ///
-    /// 
- static const char* get_data_type_name(DataType) noexcept; - - static SharedGroup::version_type get_version_of_latest_snapshot(SharedGroup&); -}; - - -// Implementation: - -inline Table* LangBindHelper::new_table() -{ - typedef _impl::TableFriend tf; - Allocator& alloc = Allocator::get_default(); - size_t ref = tf::create_empty_table(alloc); // Throws - Table::Parent* parent = nullptr; - size_t ndx_in_parent = 0; - Table* table = tf::create_accessor(alloc, ref, parent, ndx_in_parent); // Throws - bind_table_ptr(table); - return table; -} - -inline Table* LangBindHelper::copy_table(const Table& table) -{ - typedef _impl::TableFriend tf; - Allocator& alloc = Allocator::get_default(); - size_t ref = tf::clone(table, alloc); // Throws - Table::Parent* parent = nullptr; - size_t ndx_in_parent = 0; - Table* copy_of_table = tf::create_accessor(alloc, ref, parent, ndx_in_parent); // Throws - bind_table_ptr(copy_of_table); - return copy_of_table; -} - -inline Table* LangBindHelper::get_subtable_ptr(Table* t, size_t column_ndx, size_t row_ndx) -{ - Table* subtab = t->get_subtable_ptr(column_ndx, row_ndx); // Throws - subtab->bind_ptr(); - return subtab; -} - -inline const Table* LangBindHelper::get_subtable_ptr(const Table* t, size_t column_ndx, size_t row_ndx) -{ - const Table* subtab = t->get_subtable_ptr(column_ndx, row_ndx); // Throws - subtab->bind_ptr(); - return subtab; -} - -inline Table* LangBindHelper::get_subtable_ptr(TableView* tv, size_t column_ndx, size_t row_ndx) -{ - return get_subtable_ptr(&tv->get_parent(), column_ndx, tv->get_source_ndx(row_ndx)); -} - -inline const Table* LangBindHelper::get_subtable_ptr(const TableView* tv, size_t column_ndx, size_t row_ndx) -{ - return get_subtable_ptr(&tv->get_parent(), column_ndx, tv->get_source_ndx(row_ndx)); -} - -inline const Table* LangBindHelper::get_subtable_ptr(const ConstTableView* tv, size_t column_ndx, size_t row_ndx) -{ - return get_subtable_ptr(&tv->get_parent(), column_ndx, tv->get_source_ndx(row_ndx)); -} - -inline Table* LangBindHelper::get_table(Group& group, size_t index_in_group) -{ - typedef _impl::GroupFriend gf; - Table* table = &gf::get_table(group, index_in_group); // Throws - table->bind_ptr(); - return table; -} - -inline const Table* LangBindHelper::get_table(const Group& group, size_t index_in_group) -{ - typedef _impl::GroupFriend gf; - const Table* table = &gf::get_table(group, index_in_group); // Throws - table->bind_ptr(); - return table; -} - -inline Table* LangBindHelper::get_table(Group& group, StringData name) -{ - typedef _impl::GroupFriend gf; - Table* table = gf::get_table(group, name); // Throws - if (table) - table->bind_ptr(); - return table; -} - -inline const Table* LangBindHelper::get_table(const Group& group, StringData name) -{ - typedef _impl::GroupFriend gf; - const Table* table = gf::get_table(group, name); // Throws - if (table) - table->bind_ptr(); - return table; -} - -inline Table* LangBindHelper::add_table(Group& group, StringData name, bool require_unique_name) -{ - typedef _impl::GroupFriend gf; - Table* table = &gf::add_table(group, name, require_unique_name); // Throws - table->bind_ptr(); - return table; -} - -inline Table* LangBindHelper::get_or_add_table(Group& group, StringData name, bool* was_added) -{ - typedef _impl::GroupFriend gf; - Table* table = &gf::get_or_add_table(group, name, was_added); // Throws - table->bind_ptr(); - return table; -} - -inline void LangBindHelper::unbind_table_ptr(const Table* t) noexcept -{ - t->unbind_ptr(); -} - -inline void LangBindHelper::bind_table_ptr(const Table* t) noexcept -{ - t->bind_ptr(); -} - -inline void LangBindHelper::set_mixed_subtable(Table& parent, size_t col_ndx, size_t row_ndx, const Table& source) -{ - parent.set_mixed_subtable(col_ndx, row_ndx, &source); -} - -inline const LinkViewRef& LangBindHelper::get_linklist_ptr(Row& row, size_t col_ndx) -{ - LinkViewRef* link_view = new LinkViewRef(row.get_linklist(col_ndx)); - return *link_view; -} - -inline void LangBindHelper::unbind_linklist_ptr(const LinkViewRef& link_view) -{ - delete (&link_view); -} - -inline void LangBindHelper::advance_read(SharedGroup& sg, VersionID version) -{ - using sgf = _impl::SharedGroupFriend; - _impl::NullInstructionObserver* observer = nullptr; - sgf::advance_read(sg, observer, version); // Throws -} - -template -inline void LangBindHelper::advance_read(SharedGroup& sg, O&& observer, VersionID version) -{ - using sgf = _impl::SharedGroupFriend; - sgf::advance_read(sg, &observer, version); // Throws -} - -inline void LangBindHelper::promote_to_write(SharedGroup& sg) -{ - using sgf = _impl::SharedGroupFriend; - _impl::NullInstructionObserver* observer = nullptr; - sgf::promote_to_write(sg, observer); // Throws -} - -template -inline void LangBindHelper::promote_to_write(SharedGroup& sg, O&& observer) -{ - using sgf = _impl::SharedGroupFriend; - sgf::promote_to_write(sg, &observer); // Throws -} - -inline SharedGroup::version_type LangBindHelper::commit_and_continue_as_read(SharedGroup& sg) -{ - using sgf = _impl::SharedGroupFriend; - return sgf::commit_and_continue_as_read(sg); // Throws -} - -inline void LangBindHelper::rollback_and_continue_as_read(SharedGroup& sg) -{ - using sgf = _impl::SharedGroupFriend; - _impl::NullInstructionObserver* observer = nullptr; - sgf::rollback_and_continue_as_read(sg, observer); // Throws -} - -template -inline void LangBindHelper::rollback_and_continue_as_read(SharedGroup& sg, O&& observer) -{ - using sgf = _impl::SharedGroupFriend; - sgf::rollback_and_continue_as_read(sg, &observer); // Throws -} - -inline SharedGroup::version_type LangBindHelper::get_version_of_latest_snapshot(SharedGroup& sg) -{ - using sgf = _impl::SharedGroupFriend; - return sgf::get_version_of_latest_snapshot(sg); // Throws -} - -} // namespace realm - -#endif // REALM_LANG_BIND_HELPER_HPP diff --git a/Example/Pods/Realm/include/core/realm/link_view.hpp b/Example/Pods/Realm/include/core/realm/link_view.hpp deleted file mode 100644 index 89ce9da..0000000 --- a/Example/Pods/Realm/include/core/realm/link_view.hpp +++ /dev/null @@ -1,375 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_LINK_VIEW_HPP -#define REALM_LINK_VIEW_HPP - -#include -#include -#include -#include - -namespace realm { - -class LinkListColumn; - -namespace _impl { -class LinkListFriend; -class TransactLogConvenientEncoder; -} - - -/// The effect of calling most of the link list functions on a detached accessor -/// is unspecified and may lead to general corruption, or even a crash. The -/// exceptions are is_attached() and the destructor. -/// -/// FIXME: Rename this class to `LinkList`. -class LinkView : public RowIndexes, public std::enable_shared_from_this { -public: - ~LinkView() noexcept; - bool is_attached() const noexcept; - - /// This method will return true if the LinkView is detached (no assert). - bool is_empty() const noexcept; - - /// This method will return 0 if the LinkView is detached (no assert). - size_t size() const noexcept override; - - bool operator==(const LinkView&) const noexcept; - bool operator!=(const LinkView&) const noexcept; - - // Getting links - Table::ConstRowExpr operator[](size_t link_ndx) const noexcept; - Table::RowExpr operator[](size_t link_ndx) noexcept; - Table::ConstRowExpr get(size_t link_ndx) const noexcept; - Table::RowExpr get(size_t link_ndx) noexcept; - - // Modifiers - void add(size_t target_row_ndx); - void insert(size_t link_ndx, size_t target_row_ndx); - void set(size_t link_ndx, size_t target_row_ndx); - /// Move the link at \a from_ndx such that it ends up at \a to_ndx. Other - /// links are shifted as necessary in such a way that their order is - /// preserved. - /// - /// Note that \a to_ndx is the desired final index of the moved link, - /// therefore, `move(1,1)` is a no-op, while `move(1,2)` moves the link at - /// index 1 by one position, such that it ends up at index 2. A side-effect - /// of that, is that the link, that was originally at index 2, is moved to - /// index 1. - void move(size_t from_ndx, size_t to_ndx); - void swap(size_t link1_ndx, size_t link2_ndx); - void remove(size_t link_ndx); - void clear(); - - void sort(size_t column, bool ascending = true); - void sort(const SortDescriptor& order); - - TableView get_sorted_view(size_t column_index, bool ascending = true) const; - TableView get_sorted_view(SortDescriptor order) const; - - /// Remove the target row of the specified link from the target table. This - /// also removes the specified link from this link list, and any other link - /// pointing to that row. This is merely a shorthand for - /// `get_target_table.move_last_over(get(link_ndx))`. - void remove_target_row(size_t link_ndx); - - /// Remove all target rows pointed to by links in this link list, and clear - /// this link list. - void remove_all_target_rows(); - - /// Search this list for a link to the specified target table row (specified - /// by its index in the target table). If found, the index of the link to - /// that row within this list is returned, otherwise `realm::not_found` is - /// returned. - size_t find(size_t target_row_ndx, size_t start = 0) const noexcept; - - const ColumnBase& get_column_base(size_t index) - const override; // FIXME: `ColumnBase` is not part of the public API, so this function must be made private. - const Table& get_origin_table() const noexcept; - Table& get_origin_table() noexcept; - - size_t get_origin_row_index() const noexcept; - - const Table& get_target_table() const noexcept; - Table& get_target_table() noexcept; - - // No-op because LinkViews are always kept in sync. - uint_fast64_t sync_if_needed() const override; - bool is_in_sync() const override - { - return true; - } - -private: - struct ctor_cookie { - }; - - TableRef m_origin_table; - LinkListColumn& m_origin_column; - - using HandoverPatch = LinkViewHandoverPatch; - static void generate_patch(const ConstLinkViewRef& ref, std::unique_ptr& patch); - static LinkViewRef create_from_and_consume_patch(std::unique_ptr& patch, Group& group); - - void detach(); - void set_origin_row_index(size_t row_ndx) noexcept; - - void do_insert(size_t link_ndx, size_t target_row_ndx); - size_t do_set(size_t link_ndx, size_t target_row_ndx); - size_t do_remove(size_t link_ndx); - void do_clear(bool broken_reciprocal_backlinks); - - void do_nullify_link(size_t old_target_row_ndx); - void do_update_link(size_t old_target_row_ndx, size_t new_target_row_ndx); - void do_swap_link(size_t target_row_ndx_1, size_t target_row_ndx_2); - - void refresh_accessor_tree(size_t new_row_ndx) noexcept; - - void update_from_parent(size_t old_baseline) noexcept; - - Replication* get_repl() noexcept; - void repl_unselect() noexcept; - friend class _impl::TransactLogConvenientEncoder; - -#ifdef REALM_DEBUG - void verify(size_t row_ndx) const; -#endif - // allocate using make_shared: - static std::shared_ptr create(Table* origin_table, LinkListColumn&, size_t row_ndx); - - friend class _impl::LinkListFriend; - friend class LinkListColumn; - friend class LangBindHelper; - friend class SharedGroup; - friend class Query; - friend class TableViewBase; - - // must be public for use by make_shared, but cannot be called from outside, - // because ctor_cookie is private -public: - LinkView(const ctor_cookie&, Table* origin_table, LinkListColumn&, size_t row_ndx); -}; - - -// Implementation - -inline LinkView::LinkView(const ctor_cookie&, Table* origin_table, LinkListColumn& column, size_t row_ndx) - : RowIndexes(IntegerColumn::unattached_root_tag(), column.get_alloc()) // Throws - , m_origin_table(origin_table->get_table_ref()) - , m_origin_column(column) -{ - m_row_indexes.set_parent(&m_origin_column, row_ndx); - m_row_indexes.init_from_parent(); -} - -inline std::shared_ptr LinkView::create(Table* origin_table, LinkListColumn& column, size_t row_ndx) -{ - return std::make_shared(ctor_cookie(), origin_table, column, row_ndx); -} - -inline LinkView::~LinkView() noexcept -{ - if (is_attached()) { - repl_unselect(); - m_origin_column.unregister_linkview(); - } -} - -inline void LinkView::detach() -{ - REALM_ASSERT(is_attached()); - repl_unselect(); - m_origin_table.reset(); - m_row_indexes.detach(); -} - -inline bool LinkView::is_attached() const noexcept -{ - return static_cast(m_origin_table); -} - -inline bool LinkView::is_empty() const noexcept -{ - if (!is_attached()) - return true; - - if (!m_row_indexes.is_attached()) - return true; - - return m_row_indexes.is_empty(); -} - -inline size_t LinkView::size() const noexcept -{ - if (!is_attached()) - return 0; - - if (!m_row_indexes.is_attached()) - return 0; - - return m_row_indexes.size(); -} - -inline bool LinkView::operator==(const LinkView& link_list) const noexcept -{ - Table& target_table_1 = m_origin_column.get_target_table(); - Table& target_table_2 = link_list.m_origin_column.get_target_table(); - if (target_table_1.get_index_in_group() != target_table_2.get_index_in_group()) - return false; - if (!m_row_indexes.is_attached() || m_row_indexes.is_empty()) { - return !link_list.m_row_indexes.is_attached() || link_list.m_row_indexes.is_empty(); - } - return link_list.m_row_indexes.is_attached() && m_row_indexes.compare(link_list.m_row_indexes); -} - -inline bool LinkView::operator!=(const LinkView& link_list) const noexcept -{ - return !(*this == link_list); -} - -inline Table::ConstRowExpr LinkView::get(size_t link_ndx) const noexcept -{ - return const_cast(this)->get(link_ndx); -} - -inline Table::RowExpr LinkView::get(size_t link_ndx) noexcept -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT(m_row_indexes.is_attached()); - REALM_ASSERT_3(link_ndx, <, m_row_indexes.size()); - - Table& target_table = m_origin_column.get_target_table(); - size_t target_row_ndx = to_size_t(m_row_indexes.get(link_ndx)); - return target_table[target_row_ndx]; -} - -inline Table::ConstRowExpr LinkView::operator[](size_t link_ndx) const noexcept -{ - return get(link_ndx); -} - -inline Table::RowExpr LinkView::operator[](size_t link_ndx) noexcept -{ - return get(link_ndx); -} - -inline void LinkView::add(size_t target_row_ndx) -{ - REALM_ASSERT(is_attached()); - size_t ins_pos = (m_row_indexes.is_attached()) ? m_row_indexes.size() : 0; - insert(ins_pos, target_row_ndx); -} - -inline size_t LinkView::find(size_t target_row_ndx, size_t start) const noexcept -{ - REALM_ASSERT(is_attached()); - REALM_ASSERT_3(target_row_ndx, <, m_origin_column.get_target_table().size()); - REALM_ASSERT_3(start, <=, size()); - - if (!m_row_indexes.is_attached()) - return not_found; - - return m_row_indexes.find_first(target_row_ndx, start); -} - -inline const ColumnBase& LinkView::get_column_base(size_t index) const -{ - return get_target_table().get_column_base(index); -} - -inline const Table& LinkView::get_origin_table() const noexcept -{ - return *m_origin_table; -} - -inline Table& LinkView::get_origin_table() noexcept -{ - return *m_origin_table; -} - -inline size_t LinkView::get_origin_row_index() const noexcept -{ - REALM_ASSERT(is_attached()); - return m_row_indexes.get_root_array()->get_ndx_in_parent(); -} - -inline void LinkView::set_origin_row_index(size_t row_ndx) noexcept -{ - REALM_ASSERT(is_attached()); - m_row_indexes.get_root_array()->set_ndx_in_parent(row_ndx); -} - -inline const Table& LinkView::get_target_table() const noexcept -{ - return m_origin_column.get_target_table(); -} - -inline Table& LinkView::get_target_table() noexcept -{ - return m_origin_column.get_target_table(); -} - -inline void LinkView::refresh_accessor_tree(size_t new_row_ndx) noexcept -{ - set_origin_row_index(new_row_ndx); - m_row_indexes.init_from_parent(); -} - -inline void LinkView::update_from_parent(size_t old_baseline) noexcept -{ - if (m_row_indexes.is_attached()) - m_row_indexes.update_from_parent(old_baseline); -} - -inline Replication* LinkView::get_repl() noexcept -{ - typedef _impl::TableFriend tf; - return tf::get_repl(*m_origin_table); -} - - -// The purpose of this class is to give internal access to some, but not all of -// the non-public parts of LinkView. -class _impl::LinkListFriend { -public: - static void do_set(LinkView& list, size_t link_ndx, size_t target_row_ndx) - { - list.do_set(link_ndx, target_row_ndx); - } - - static void do_remove(LinkView& list, size_t link_ndx) - { - list.do_remove(link_ndx); - } - - static void do_clear(LinkView& list) - { - bool broken_reciprocal_backlinks = false; - list.do_clear(broken_reciprocal_backlinks); - } - - static void do_insert(LinkView& list, size_t link_ndx, size_t target_row_ndx) - { - list.do_insert(link_ndx, target_row_ndx); - } -}; - -} // namespace realm - -#endif // REALM_LINK_VIEW_HPP diff --git a/Example/Pods/Realm/include/core/realm/link_view_fwd.hpp b/Example/Pods/Realm/include/core/realm/link_view_fwd.hpp deleted file mode 100644 index cba8801..0000000 --- a/Example/Pods/Realm/include/core/realm/link_view_fwd.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_LINK_VIEW_FWD_HPP -#define REALM_LINK_VIEW_FWD_HPP - -#include - -namespace realm { - -class LinkView; -using LinkViewRef = std::shared_ptr; -using ConstLinkViewRef = std::shared_ptr; - -} // namespace realm - -#endif // REALM_LINK_VIEW_FWD_HPP diff --git a/Example/Pods/Realm/include/core/realm/mixed.hpp b/Example/Pods/Realm/include/core/realm/mixed.hpp deleted file mode 100644 index 8f07f4f..0000000 --- a/Example/Pods/Realm/include/core/realm/mixed.hpp +++ /dev/null @@ -1,657 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_MIXED_HPP -#define REALM_MIXED_HPP - -#include // int64_t - not part of C++03, not even required by C++11 (see C++11 section 18.4.1) - -#include // size_t -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - - -/// This class represents a polymorphic Realm value. -/// -/// At any particular moment an instance of this class stores a -/// definite value of a definite type. If, for instance, that is an -/// integer value, you may call get_int() to extract that value. You -/// may call get_type() to discover what type of value is currently -/// stored. Calling get_int() on an instance that does not store an -/// integer, has undefined behavior, and likewise for all the other -/// types that can be stored. -/// -/// It is crucial to understand that the act of extracting a value of -/// a particular type requires definite knowledge about the stored -/// type. Calling a getter method for any particular type, that is not -/// the same type as the stored value, has undefined behavior. -/// -/// While values of numeric types are contained directly in a Mixed -/// instance, character and binary data are merely referenced. A Mixed -/// instance never owns the referenced data, nor does it in any other -/// way attempt to manage its lifetime. -/// -/// For compatibility with C style strings, when a string (character -/// data) is stored in a Realm database, it is always followed by a -/// terminating null character. This is also true when strings are -/// stored in a mixed type column. This means that in the following -/// code, if the 'mixed' value of the 8th row stores a string, then \c -/// c_str will always point to a null-terminated string: -/// -/// \code{.cpp} -/// -/// const char* c_str = my_table[7].mixed.data(); // Always null-terminated -/// -/// \endcode -/// -/// Note that this assumption does not hold in general for strings in -/// instances of Mixed. Indeed there is nothing stopping you from -/// constructing a new Mixed instance that refers to a string without -/// a terminating null character. -/// -/// At the present time no soultion has been found that would allow -/// for a Mixed instance to directly store a reference to a table. The -/// problem is roughly as follows: From most points of view, the -/// desirable thing to do, would be to store the table reference in a -/// Mixed instance as a plain pointer without any ownership -/// semantics. This would have no negative impact on the performance -/// of copying and destroying Mixed instances, and it would serve just -/// fine for passing a table as argument when setting the value of an -/// entry in a mixed column. In that case a copy of the referenced -/// table would be inserted into the mixed column. -/// -/// On the other hand, when retrieving a table reference from a mixed -/// column, storing it as a plain pointer in a Mixed instance is no -/// longer an acceptable option. The complex rules for managing the -/// lifetime of a Table instance, that represents a subtable, -/// necessitates the use of a "smart pointer" such as -/// TableRef. Enhancing the Mixed class to be able to act as a -/// TableRef would be possible, but would also lead to several new -/// problems. One problem is the risk of a Mixed instance outliving a -/// stack allocated Table instance that it references. This would be a -/// fatal error. Another problem is the impact that the nontrivial -/// table reference has on the performance of copying and destroying -/// Mixed instances. -/// -/// \sa StringData -class Mixed { -public: - Mixed() noexcept; - - Mixed(bool) noexcept; - Mixed(int64_t) noexcept; - Mixed(float) noexcept; - Mixed(double) noexcept; - Mixed(StringData) noexcept; - Mixed(BinaryData) noexcept; - Mixed(OldDateTime) noexcept; - Mixed(Timestamp) noexcept; - - // These are shortcuts for Mixed(StringData(c_str)), and are - // needed to avoid unwanted implicit conversion of char* to bool. - Mixed(char* c_str) noexcept - { - set_string(c_str); - } - Mixed(const char* c_str) noexcept - { - set_string(c_str); - } - - struct subtable_tag { - }; - Mixed(subtable_tag) noexcept - : m_type(type_Table) - { - } - - ~Mixed() noexcept - { - } - - DataType get_type() const noexcept - { - return m_type; - } - - int64_t get_int() const noexcept; - bool get_bool() const noexcept; - float get_float() const noexcept; - double get_double() const noexcept; - StringData get_string() const noexcept; - BinaryData get_binary() const noexcept; - OldDateTime get_olddatetime() const noexcept; - Timestamp get_timestamp() const noexcept; - - void set_int(int64_t) noexcept; - void set_bool(bool) noexcept; - void set_float(float) noexcept; - void set_double(double) noexcept; - void set_string(StringData) noexcept; - void set_binary(BinaryData) noexcept; - void set_binary(const char* data, size_t size) noexcept; - void set_olddatetime(OldDateTime) noexcept; - void set_timestamp(Timestamp) noexcept; - - template - friend std::basic_ostream& operator<<(std::basic_ostream&, const Mixed&); - -private: - DataType m_type; - union { - int64_t m_int; - bool m_bool; - float m_float; - double m_double; - const char* m_data; - int_fast64_t m_date; - Timestamp m_timestamp; - }; - size_t m_size = 0; -}; - -// Note: We cannot compare two mixed values, since when the type of -// both is type_Table, we would have to compare the two tables, but -// the mixed values do not provide access to those tables. - -// Note: The mixed values are specified as Wrap. If they were -// not, these operators would apply to simple comparisons, such as int -// vs int64_t, and cause ambiguity. This is because the constructors -// of Mixed are not explicit. - -// Compare mixed with integer -template -bool operator==(Wrap, const T&) noexcept; -template -bool operator!=(Wrap, const T&) noexcept; -template -bool operator==(const T&, Wrap) noexcept; -template -bool operator!=(const T&, Wrap) noexcept; - -// Compare mixed with boolean -bool operator==(Wrap, bool) noexcept; -bool operator!=(Wrap, bool) noexcept; -bool operator==(bool, Wrap) noexcept; -bool operator!=(bool, Wrap) noexcept; - -// Compare mixed with float -bool operator==(Wrap, float); -bool operator!=(Wrap, float); -bool operator==(float, Wrap); -bool operator!=(float, Wrap); - -// Compare mixed with double -bool operator==(Wrap, double); -bool operator!=(Wrap, double); -bool operator==(double, Wrap); -bool operator!=(double, Wrap); - -// Compare mixed with string -bool operator==(Wrap, StringData) noexcept; -bool operator!=(Wrap, StringData) noexcept; -bool operator==(StringData, Wrap) noexcept; -bool operator!=(StringData, Wrap) noexcept; -bool operator==(Wrap, const char* c_str) noexcept; -bool operator!=(Wrap, const char* c_str) noexcept; -bool operator==(const char* c_str, Wrap) noexcept; -bool operator!=(const char* c_str, Wrap) noexcept; -bool operator==(Wrap, char* c_str) noexcept; -bool operator!=(Wrap, char* c_str) noexcept; -bool operator==(char* c_str, Wrap) noexcept; -bool operator!=(char* c_str, Wrap) noexcept; - -// Compare mixed with binary data -bool operator==(Wrap, BinaryData) noexcept; -bool operator!=(Wrap, BinaryData) noexcept; -bool operator==(BinaryData, Wrap) noexcept; -bool operator!=(BinaryData, Wrap) noexcept; - -// Compare mixed with date -bool operator==(Wrap, OldDateTime) noexcept; -bool operator!=(Wrap, OldDateTime) noexcept; -bool operator==(OldDateTime, Wrap) noexcept; -bool operator!=(OldDateTime, Wrap) noexcept; - - -// Implementation: - -inline Mixed::Mixed() noexcept -{ - m_type = type_Int; - m_int = 0; -} - -inline Mixed::Mixed(int64_t v) noexcept -{ - m_type = type_Int; - m_int = v; -} - -inline Mixed::Mixed(bool v) noexcept -{ - m_type = type_Bool; - m_bool = v; -} - -inline Mixed::Mixed(float v) noexcept -{ - m_type = type_Float; - m_float = v; -} - -inline Mixed::Mixed(double v) noexcept -{ - m_type = type_Double; - m_double = v; -} - -inline Mixed::Mixed(StringData v) noexcept -{ - m_type = type_String; - m_data = v.data(); - m_size = v.size(); -} - -inline Mixed::Mixed(BinaryData v) noexcept -{ - m_type = type_Binary; - m_data = v.data(); - m_size = v.size(); -} - -inline Mixed::Mixed(OldDateTime v) noexcept -{ - m_type = type_OldDateTime; - m_date = v.get_olddatetime(); -} - -inline Mixed::Mixed(Timestamp v) noexcept -{ - m_type = type_Timestamp; - m_timestamp = v; -} - -inline int64_t Mixed::get_int() const noexcept -{ - REALM_ASSERT(m_type == type_Int); - return m_int; -} - -inline bool Mixed::get_bool() const noexcept -{ - REALM_ASSERT(m_type == type_Bool); - return m_bool; -} - -inline float Mixed::get_float() const noexcept -{ - REALM_ASSERT(m_type == type_Float); - return m_float; -} - -inline double Mixed::get_double() const noexcept -{ - REALM_ASSERT(m_type == type_Double); - return m_double; -} - -inline StringData Mixed::get_string() const noexcept -{ - REALM_ASSERT(m_type == type_String); - return StringData(m_data, m_size); -} - -inline BinaryData Mixed::get_binary() const noexcept -{ - REALM_ASSERT(m_type == type_Binary); - return BinaryData(m_data, m_size); -} - -inline OldDateTime Mixed::get_olddatetime() const noexcept -{ - REALM_ASSERT(m_type == type_OldDateTime); - return m_date; -} - -inline Timestamp Mixed::get_timestamp() const noexcept -{ - REALM_ASSERT(m_type == type_Timestamp); - return m_timestamp; -} - -inline void Mixed::set_int(int64_t v) noexcept -{ - m_type = type_Int; - m_int = v; -} - -inline void Mixed::set_bool(bool v) noexcept -{ - m_type = type_Bool; - m_bool = v; -} - -inline void Mixed::set_float(float v) noexcept -{ - m_type = type_Float; - m_float = v; -} - -inline void Mixed::set_double(double v) noexcept -{ - m_type = type_Double; - m_double = v; -} - -inline void Mixed::set_string(StringData v) noexcept -{ - m_type = type_String; - m_data = v.data(); - m_size = v.size(); -} - -inline void Mixed::set_binary(BinaryData v) noexcept -{ - set_binary(v.data(), v.size()); -} - -inline void Mixed::set_binary(const char* data, size_t size) noexcept -{ - m_type = type_Binary; - m_data = data; - m_size = size; -} - -inline void Mixed::set_olddatetime(OldDateTime v) noexcept -{ - m_type = type_OldDateTime; - m_date = v.get_olddatetime(); -} - -// LCOV_EXCL_START -inline void Mixed::set_timestamp(Timestamp v) noexcept -{ - REALM_ASSERT(false && "not yet implemented"); - m_type = type_Timestamp; - m_timestamp = v; -} -// LCOV_EXCL_STOP - -// LCOV_EXCL_START -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const Mixed& m) -{ - out << "Mixed("; - switch (m.m_type) { - case type_Int: - out << m.m_int; - break; - case type_Bool: - out << m.m_bool; - break; - case type_Float: - out << m.m_float; - break; - case type_Double: - out << m.m_double; - break; - case type_String: - out << StringData(m.m_data, m.m_size); - break; - case type_Binary: - out << BinaryData(m.m_data, m.m_size); - break; - case type_OldDateTime: - out << OldDateTime(m.m_date); - break; - case type_Timestamp: - out << Timestamp(m.m_timestamp); - break; - case type_Table: - out << "subtable"; - break; - case type_Mixed: - case type_Link: - case type_LinkList: - REALM_ASSERT(false); - } - out << ")"; - return out; -} -// LCOV_EXCL_STOP - - -// Compare mixed with integer - -template -inline bool operator==(Wrap a, const T& b) noexcept -{ - return Mixed(a).get_type() == type_Int && Mixed(a).get_int() == b; -} - -template -inline bool operator!=(Wrap a, const T& b) noexcept -{ - return Mixed(a).get_type() != type_Int || Mixed(a).get_int() != b; -} - -template -inline bool operator==(const T& a, Wrap b) noexcept -{ - return type_Int == Mixed(b).get_type() && a == Mixed(b).get_int(); -} - -template -inline bool operator!=(const T& a, Wrap b) noexcept -{ - return type_Int != Mixed(b).get_type() || a != Mixed(b).get_int(); -} - - -// Compare mixed with boolean - -inline bool operator==(Wrap a, bool b) noexcept -{ - return Mixed(a).get_type() == type_Bool && Mixed(a).get_bool() == b; -} - -inline bool operator!=(Wrap a, bool b) noexcept -{ - return Mixed(a).get_type() != type_Bool || Mixed(a).get_bool() != b; -} - -inline bool operator==(bool a, Wrap b) noexcept -{ - return type_Bool == Mixed(b).get_type() && a == Mixed(b).get_bool(); -} - -inline bool operator!=(bool a, Wrap b) noexcept -{ - return type_Bool != Mixed(b).get_type() || a != Mixed(b).get_bool(); -} - - -// Compare mixed with float - -inline bool operator==(Wrap a, float b) -{ - return Mixed(a).get_type() == type_Float && Mixed(a).get_float() == b; -} - -inline bool operator!=(Wrap a, float b) -{ - return Mixed(a).get_type() != type_Float || Mixed(a).get_float() != b; -} - -inline bool operator==(float a, Wrap b) -{ - return type_Float == Mixed(b).get_type() && a == Mixed(b).get_float(); -} - -inline bool operator!=(float a, Wrap b) -{ - return type_Float != Mixed(b).get_type() || a != Mixed(b).get_float(); -} - - -// Compare mixed with double - -inline bool operator==(Wrap a, double b) -{ - return Mixed(a).get_type() == type_Double && Mixed(a).get_double() == b; -} - -inline bool operator!=(Wrap a, double b) -{ - return Mixed(a).get_type() != type_Double || Mixed(a).get_double() != b; -} - -inline bool operator==(double a, Wrap b) -{ - return type_Double == Mixed(b).get_type() && a == Mixed(b).get_double(); -} - -inline bool operator!=(double a, Wrap b) -{ - return type_Double != Mixed(b).get_type() || a != Mixed(b).get_double(); -} - - -// Compare mixed with string - -inline bool operator==(Wrap a, StringData b) noexcept -{ - return Mixed(a).get_type() == type_String && Mixed(a).get_string() == b; -} - -inline bool operator!=(Wrap a, StringData b) noexcept -{ - return Mixed(a).get_type() != type_String || Mixed(a).get_string() != b; -} - -inline bool operator==(StringData a, Wrap b) noexcept -{ - return type_String == Mixed(b).get_type() && a == Mixed(b).get_string(); -} - -inline bool operator!=(StringData a, Wrap b) noexcept -{ - return type_String != Mixed(b).get_type() || a != Mixed(b).get_string(); -} - -inline bool operator==(Wrap a, const char* b) noexcept -{ - return a == StringData(b); -} - -inline bool operator!=(Wrap a, const char* b) noexcept -{ - return a != StringData(b); -} - -inline bool operator==(const char* a, Wrap b) noexcept -{ - return StringData(a) == b; -} - -inline bool operator!=(const char* a, Wrap b) noexcept -{ - return StringData(a) != b; -} - -inline bool operator==(Wrap a, char* b) noexcept -{ - return a == StringData(b); -} - -inline bool operator!=(Wrap a, char* b) noexcept -{ - return a != StringData(b); -} - -inline bool operator==(char* a, Wrap b) noexcept -{ - return StringData(a) == b; -} - -inline bool operator!=(char* a, Wrap b) noexcept -{ - return StringData(a) != b; -} - - -// Compare mixed with binary data - -inline bool operator==(Wrap a, BinaryData b) noexcept -{ - return Mixed(a).get_type() == type_Binary && Mixed(a).get_binary() == b; -} - -inline bool operator!=(Wrap a, BinaryData b) noexcept -{ - return Mixed(a).get_type() != type_Binary || Mixed(a).get_binary() != b; -} - -inline bool operator==(BinaryData a, Wrap b) noexcept -{ - return type_Binary == Mixed(b).get_type() && a == Mixed(b).get_binary(); -} - -inline bool operator!=(BinaryData a, Wrap b) noexcept -{ - return type_Binary != Mixed(b).get_type() || a != Mixed(b).get_binary(); -} - - -// Compare mixed with date - -inline bool operator==(Wrap a, OldDateTime b) noexcept -{ - return Mixed(a).get_type() == type_OldDateTime && OldDateTime(Mixed(a).get_olddatetime()) == b; -} - -inline bool operator!=(Wrap a, OldDateTime b) noexcept -{ - return Mixed(a).get_type() != type_OldDateTime || OldDateTime(Mixed(a).get_olddatetime()) != b; -} - -inline bool operator==(OldDateTime a, Wrap b) noexcept -{ - return type_OldDateTime == Mixed(b).get_type() && a == OldDateTime(Mixed(b).get_olddatetime()); -} - -inline bool operator!=(OldDateTime a, Wrap b) noexcept -{ - return type_OldDateTime != Mixed(b).get_type() || a != OldDateTime(Mixed(b).get_olddatetime()); -} - - -} // namespace realm - -#endif // REALM_MIXED_HPP diff --git a/Example/Pods/Realm/include/core/realm/null.hpp b/Example/Pods/Realm/include/core/realm/null.hpp deleted file mode 100644 index be010b8..0000000 --- a/Example/Pods/Realm/include/core/realm/null.hpp +++ /dev/null @@ -1,164 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_NULL_HPP -#define REALM_NULL_HPP - -#include - -#include -#include -#include -#include - -namespace realm { - -/* -Represents null in Query, find(), get(), set(), etc. - -Float/Double: Realm can both store user-given NaNs and null. Any user-given signaling NaN is converted to -0x7fa00000 (if float) or 0x7ff4000000000000 (if double). Any user-given quiet NaN is converted to -0x7fc00000 (if float) or 0x7ff8000000000000 (if double). So Realm does not preserve the optional bits in -user-given NaNs. - -However, since both clang and gcc on x64 and ARM, and also Java on x64, return these bit patterns when -requesting NaNs, these will actually seem to roundtrip bit-exact for the end-user in most cases. - -If set_null() is called, a null is stored in form of the bit pattern 0xffffffff (if float) or -0xffffffffffffffff (if double). These are quiet NaNs. - -Executing a query that involves a float/double column that contains NaNs gives an undefined result. If -it contains signaling NaNs, it may throw an exception. - -Notes on IEEE: - -A NaN float is any bit pattern `s 11111111 S xxxxxxxxxxxxxxxxxxxxxx` where `s` and `x` are arbitrary, but at -least 1 `x` must be 1. If `S` is 1, it's a quiet NaN, else it's a signaling NaN. - -A NaN doubule is the same as above, but for `s eeeeeeeeeee S xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` - -The `S` bit is at position 22 (float) or 51 (double). -*/ - -struct null { - null() - { - } - operator int64_t() - { - throw(LogicError::type_mismatch); - } - template - operator util::Optional() - { - return util::none; - } - - template - bool operator==(const T&) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator!=(const T&) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator>(const T&) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator>=(const T&) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator<=(const T&) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator<(const T&) const - { - REALM_ASSERT(false); - return false; - } - - /// Returns whether `v` bitwise equals the null bit-pattern - template - static bool is_null_float(T v) - { - T i = null::get_null_float(); - return std::memcmp(&i, &v, sizeof(T)) == 0; - } - - /// Returns the quiet NaNs that represent null for floats/doubles in Realm in stored payload. - template - static T get_null_float() - { - typename std::conditional::value, uint32_t, uint64_t>::type i; - int64_t double_nan = 0x7ff80000000000aa; - i = std::is_same::value ? 0x7fc000aa : static_cast(double_nan); - T d = type_punning(i); - REALM_ASSERT_DEBUG(std::isnan(d)); - REALM_ASSERT_DEBUG(!is_signaling(d)); - return d; - } - - /// Takes a NaN as argument and returns whether or not it's signaling - template - static bool is_signaling(T v) - { - REALM_ASSERT(std::isnan(static_cast(v))); - typename std::conditional::value, uint32_t, uint64_t>::type i; - size_t signal_bit = std::is_same::value ? 22 : 51; // If this bit is set, it's quiet - i = type_punning(v); - return !(i & (1ull << signal_bit)); - } - - /// Converts any signaling or quiet NaN to their their respective bit patterns that are used on x64 gcc+clang, - /// ARM clang and x64 Java. - template - static T to_realm(T v) - { - if (std::isnan(static_cast(v))) { - typename std::conditional::value, uint32_t, uint64_t>::type i; - if (std::is_same::value) { - i = is_signaling(v) ? 0x7fa00000 : 0x7fc00000; - } - else { - i = static_cast(is_signaling(v) ? 0x7ff4000000000000 : 0x7ff8000000000000); - } - return type_punning(i); - } - else { - return v; - } - } -}; - -} // namespace realm - -#endif // REALM_NULL_HPP diff --git a/Example/Pods/Realm/include/core/realm/olddatetime.hpp b/Example/Pods/Realm/include/core/realm/olddatetime.hpp deleted file mode 100644 index b662899..0000000 --- a/Example/Pods/Realm/include/core/realm/olddatetime.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_DATETIME_HPP -#define REALM_DATETIME_HPP - -#include -#include - -namespace realm { - - -class OldDateTime { -public: - OldDateTime() noexcept - : m_time(0) - { - } - - /// Construct from the number of seconds since Jan 1 00:00:00 UTC - /// 1970. - /// FIXME: See if we can make this private again. Required by query_expression.hpp - OldDateTime(int_fast64_t d) noexcept - : m_time(d) - { - } - - /// Return the time as seconds since Jan 1 00:00:00 UTC 1970. - int_fast64_t get_olddatetime() const noexcept - { - return m_time; - } - - friend bool operator==(const OldDateTime&, const OldDateTime&) noexcept; - friend bool operator!=(const OldDateTime&, const OldDateTime&) noexcept; - friend bool operator<(const OldDateTime&, const OldDateTime&) noexcept; - friend bool operator<=(const OldDateTime&, const OldDateTime&) noexcept; - friend bool operator>(const OldDateTime&, const OldDateTime&) noexcept; - friend bool operator>=(const OldDateTime&, const OldDateTime&) noexcept; - - /// Construct from broken down local time. - /// - /// \note This constructor uses std::mktime() to convert the - /// specified local time to seconds since the Epoch, that is, the - /// result depends on the current globally specified time zone - /// setting. - /// - /// \param year The year (the minimum valid value is 1970). - /// - /// \param month The month in the range [1, 12]. - /// - /// \param day The day of the month in the range [1, 31]. - /// - /// \param hours Hours since midnight in the range [0, 23]. - /// - /// \param minutes Minutes after the hour in the range [0, 59]. - /// - /// \param seconds Seconds after the minute in the range [0, - /// 60]. Note that the range allows for leap seconds. - OldDateTime(int year, int month, int day, int hours = 0, int minutes = 0, int seconds = 0); - - template - friend std::basic_ostream& operator<<(std::basic_ostream& out, const OldDateTime&); - - // This is used by query_expression.hpp to generalize its templates and simplify the code *alot*; it is needed - // because OldDateTime is internally stored in an int64_t column. - operator int_fast64_t() noexcept; - -private: - int_fast64_t m_time; // Seconds since Jan 1 00:00:00 UTC 1970. - static std::time_t assemble(int year, int month, int day, int hours, int minutes, int seconds); - template - friend class Value; -}; - - -// Implementation: - -inline bool operator==(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time == b.m_time; -} - -inline bool operator!=(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time != b.m_time; -} - -inline bool operator<(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time < b.m_time; -} - -inline bool operator<=(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time <= b.m_time; -} - -inline bool operator>(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time > b.m_time; -} - -inline bool operator>=(const OldDateTime& a, const OldDateTime& b) noexcept -{ - return a.m_time >= b.m_time; -} - -inline OldDateTime::operator int_fast64_t() noexcept -{ - return m_time; -} - -inline OldDateTime::OldDateTime(int year, int month, int day, int hours, int minutes, int seconds) - : m_time(assemble(year, month, day, hours, minutes, seconds)) -{ -} - -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const OldDateTime& d) -{ - out << "OldDateTime(" << d.m_time << ")"; - return out; -} - -inline std::time_t OldDateTime::assemble(int year, int month, int day, int hours, int minutes, int seconds) -{ - std::tm local_time; - local_time.tm_year = year - 1900; - local_time.tm_mon = month - 1; - local_time.tm_mday = day; - local_time.tm_hour = hours; - local_time.tm_min = minutes; - local_time.tm_sec = seconds; - local_time.tm_isdst = -1; - return std::mktime(&local_time); -} - - -} // namespace realm - -#endif // REALM_DATETIME_HPP diff --git a/Example/Pods/Realm/include/core/realm/owned_data.hpp b/Example/Pods/Realm/include/core/realm/owned_data.hpp deleted file mode 100644 index 039ccc8..0000000 --- a/Example/Pods/Realm/include/core/realm/owned_data.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_OWNED_DATA_HPP -#define REALM_OWNED_DATA_HPP - -#include -#include - -namespace realm { - -/// A chunk of owned data. -class OwnedData { -public: - /// Construct a null reference. - OwnedData() noexcept - { - } - - /// If \a data_to_copy is 'null', \a data_size must be zero. - OwnedData(const char* data_to_copy, size_t data_size) - : m_size(data_size) - { - REALM_ASSERT_DEBUG(data_to_copy || data_size == 0); - if (data_to_copy) { - m_data = std::unique_ptr(new char[data_size]); - memcpy(m_data.get(), data_to_copy, data_size); - } - } - - /// If \a unique_data is 'null', \a data_size must be zero. - OwnedData(std::unique_ptr unique_data, size_t data_size) noexcept - : m_data(std::move(unique_data)) - , m_size(data_size) - { - REALM_ASSERT_DEBUG(m_data || m_size == 0); - } - - OwnedData(const OwnedData& other) - : OwnedData(other.m_data.get(), other.m_size) - { - } - OwnedData& operator=(const OwnedData& other); - - OwnedData(OwnedData&&) = default; - OwnedData& operator=(OwnedData&&) = default; - - const char* data() const - { - return m_data.get(); - } - size_t size() const - { - return m_size; - } - -private: - std::unique_ptr m_data; - size_t m_size = 0; -}; - -inline OwnedData& OwnedData::operator=(const OwnedData& other) -{ - if (this != &other) { - if (other.m_data) { - m_data = std::unique_ptr(new char[other.m_size]); - memcpy(m_data.get(), other.m_data.get(), other.m_size); - } - else { - m_data = nullptr; - } - m_size = other.m_size; - } - return *this; -} - -} // namespace realm - -#endif // REALM_OWNED_DATA_HPP diff --git a/Example/Pods/Realm/include/core/realm/query.hpp b/Example/Pods/Realm/include/core/realm/query.hpp deleted file mode 100644 index f166cd9..0000000 --- a/Example/Pods/Realm/include/core/realm/query.hpp +++ /dev/null @@ -1,458 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_QUERY_HPP -#define REALM_QUERY_HPP - -#include -#include -#include -#include -#include -#include - -#define REALM_MULTITHREAD_QUERY 0 - -#if REALM_MULTITHREAD_QUERY -// FIXME: Use our C++ thread abstraction API since it provides a much -// higher level of encapsulation and safety. -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - - -// Pre-declarations -class ParentNode; -class Table; -class TableView; -class TableViewBase; -class ConstTableView; -class Array; -class Expression; -class SequentialGetterBase; -class Group; - -struct QueryGroup { - enum class State { - Default, - OrCondition, - OrConditionChildren, - }; - - QueryGroup() = default; - - QueryGroup(const QueryGroup&); - QueryGroup& operator=(const QueryGroup&); - - QueryGroup(QueryGroup&&) = default; - QueryGroup& operator=(QueryGroup&&) = default; - - QueryGroup(const QueryGroup&, QueryNodeHandoverPatches&); - - std::unique_ptr m_root_node; - - bool m_pending_not = false; - size_t m_subtable_column = not_found; - State m_state = State::Default; -}; - -class Query final { -public: - Query(const Table& table, TableViewBase* tv = nullptr); - Query(const Table& table, std::unique_ptr); - Query(const Table& table, const LinkViewRef& lv); - Query(); - Query(std::unique_ptr); - ~Query() noexcept; - - Query(const Query& copy); - Query& operator=(const Query& source); - - Query(Query&&); - Query& operator=(Query&&); - - // Find links that point to a specific target row - Query& links_to(size_t column_ndx, const ConstRow& target_row); - - // Conditions: null - Query& equal(size_t column_ndx, null); - Query& not_equal(size_t column_ndx, null); - - // Conditions: int64_t - Query& equal(size_t column_ndx, int64_t value); - Query& not_equal(size_t column_ndx, int64_t value); - Query& greater(size_t column_ndx, int64_t value); - Query& greater_equal(size_t column_ndx, int64_t value); - Query& less(size_t column_ndx, int64_t value); - Query& less_equal(size_t column_ndx, int64_t value); - Query& between(size_t column_ndx, int64_t from, int64_t to); - - // Conditions: int (we need those because conversion from '1234' is ambiguous with float/double) - Query& equal(size_t column_ndx, int value); - Query& not_equal(size_t column_ndx, int value); - Query& greater(size_t column_ndx, int value); - Query& greater_equal(size_t column_ndx, int value); - Query& less(size_t column_ndx, int value); - Query& less_equal(size_t column_ndx, int value); - Query& between(size_t column_ndx, int from, int to); - - // Conditions: 2 int columns - Query& equal_int(size_t column_ndx1, size_t column_ndx2); - Query& not_equal_int(size_t column_ndx1, size_t column_ndx2); - Query& greater_int(size_t column_ndx1, size_t column_ndx2); - Query& less_int(size_t column_ndx1, size_t column_ndx2); - Query& greater_equal_int(size_t column_ndx1, size_t column_ndx2); - Query& less_equal_int(size_t column_ndx1, size_t column_ndx2); - - // Conditions: float - Query& equal(size_t column_ndx, float value); - Query& not_equal(size_t column_ndx, float value); - Query& greater(size_t column_ndx, float value); - Query& greater_equal(size_t column_ndx, float value); - Query& less(size_t column_ndx, float value); - Query& less_equal(size_t column_ndx, float value); - Query& between(size_t column_ndx, float from, float to); - - // Conditions: 2 float columns - Query& equal_float(size_t column_ndx1, size_t column_ndx2); - Query& not_equal_float(size_t column_ndx1, size_t column_ndx2); - Query& greater_float(size_t column_ndx1, size_t column_ndx2); - Query& greater_equal_float(size_t column_ndx1, size_t column_ndx2); - Query& less_float(size_t column_ndx1, size_t column_ndx2); - Query& less_equal_float(size_t column_ndx1, size_t column_ndx2); - - // Conditions: double - Query& equal(size_t column_ndx, double value); - Query& not_equal(size_t column_ndx, double value); - Query& greater(size_t column_ndx, double value); - Query& greater_equal(size_t column_ndx, double value); - Query& less(size_t column_ndx, double value); - Query& less_equal(size_t column_ndx, double value); - Query& between(size_t column_ndx, double from, double to); - - // Conditions: 2 double columns - Query& equal_double(size_t column_ndx1, size_t column_ndx2); - Query& not_equal_double(size_t column_ndx1, size_t column_ndx2); - Query& greater_double(size_t column_ndx1, size_t column_ndx2); - Query& greater_equal_double(size_t column_ndx1, size_t column_ndx2); - Query& less_double(size_t column_ndx1, size_t column_ndx2); - Query& less_equal_double(size_t column_ndx1, size_t column_ndx2); - - // Conditions: timestamp - Query& equal(size_t column_ndx, Timestamp value); - Query& not_equal(size_t column_ndx, Timestamp value); - Query& greater(size_t column_ndx, Timestamp value); - Query& greater_equal(size_t column_ndx, Timestamp value); - Query& less_equal(size_t column_ndx, Timestamp value); - Query& less(size_t column_ndx, Timestamp value); - - // Conditions: bool - Query& equal(size_t column_ndx, bool value); - - // Conditions: date - Query& equal_olddatetime(size_t column_ndx, OldDateTime value) - { - return equal(column_ndx, int64_t(value.get_olddatetime())); - } - Query& not_equal_olddatetime(size_t column_ndx, OldDateTime value) - { - return not_equal(column_ndx, int64_t(value.get_olddatetime())); - } - Query& greater_olddatetime(size_t column_ndx, OldDateTime value) - { - return greater(column_ndx, int64_t(value.get_olddatetime())); - } - Query& greater_equal_olddatetime(size_t column_ndx, OldDateTime value) - { - return greater_equal(column_ndx, int64_t(value.get_olddatetime())); - } - Query& less_olddatetime(size_t column_ndx, OldDateTime value) - { - return less(column_ndx, int64_t(value.get_olddatetime())); - } - Query& less_equal_olddatetime(size_t column_ndx, OldDateTime value) - { - return less_equal(column_ndx, int64_t(value.get_olddatetime())); - } - Query& between_olddatetime(size_t column_ndx, OldDateTime from, OldDateTime to) - { - return between(column_ndx, int64_t(from.get_olddatetime()), int64_t(to.get_olddatetime())); - } - - // Conditions: strings - Query& equal(size_t column_ndx, StringData value, bool case_sensitive = true); - Query& not_equal(size_t column_ndx, StringData value, bool case_sensitive = true); - Query& begins_with(size_t column_ndx, StringData value, bool case_sensitive = true); - Query& ends_with(size_t column_ndx, StringData value, bool case_sensitive = true); - Query& contains(size_t column_ndx, StringData value, bool case_sensitive = true); - Query& like(size_t column_ndx, StringData value, bool case_sensitive = true); - - // These are shortcuts for equal(StringData(c_str)) and - // not_equal(StringData(c_str)), and are needed to avoid unwanted - // implicit conversion of char* to bool. - Query& equal(size_t column_ndx, const char* c_str, bool case_sensitive = true); - Query& not_equal(size_t column_ndx, const char* c_str, bool case_sensitive = true); - - // Conditions: binary data - Query& equal(size_t column_ndx, BinaryData value); - Query& not_equal(size_t column_ndx, BinaryData value); - Query& begins_with(size_t column_ndx, BinaryData value); - Query& ends_with(size_t column_ndx, BinaryData value); - Query& contains(size_t column_ndx, BinaryData value); - - // Negation - Query& Not(); - - // Grouping - Query& group(); - Query& end_group(); - Query& subtable(size_t column); - Query& end_subtable(); - Query& Or(); - - Query& and_query(const Query& q); - Query& and_query(Query&& q); - Query operator||(const Query& q); - Query operator&&(const Query& q); - Query operator!(); - - - // Searching - size_t find(size_t begin_at_table_row = size_t(0)); - TableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)); - ConstTableView find_all(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const; - - // Aggregates - size_t count(size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const; - - int64_t sum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - double average_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - int64_t maximum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - int64_t minimum_int(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - double sum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - double average_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - float maximum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - float minimum_float(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - double sum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - double average_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - double maximum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - double minimum_double(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1), size_t* return_ndx = nullptr) const; - - OldDateTime maximum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, - size_t end = size_t(-1), size_t limit = size_t(-1), - size_t* return_ndx = nullptr) const; - - OldDateTime minimum_olddatetime(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, - size_t end = size_t(-1), size_t limit = size_t(-1), - size_t* return_ndx = nullptr) const; - - Timestamp maximum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)); - - Timestamp minimum_timestamp(size_t column_ndx, size_t* return_ndx, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)); - - // Deletion - size_t remove(); - -#if REALM_MULTITHREAD_QUERY - // Multi-threading - TableView find_all_multi(size_t start = 0, size_t end = size_t(-1)); - ConstTableView find_all_multi(size_t start = 0, size_t end = size_t(-1)) const; - int set_threads(unsigned int threadcount); -#endif - - const TableRef& get_table() - { - return m_table; - } - - // True if matching rows are guaranteed to be returned in table order. - bool produces_results_in_table_order() const - { - return !m_view; - } - - // Calls sync_if_needed on the restricting view, if present. - // Returns the current version of the table(s) this query depends on, - // or util::none if the query is not associated with a table. - util::Optional sync_view_if_needed() const; - - std::string validate(); - -private: - Query(Table& table, TableViewBase* tv = nullptr); - void create(); - - void init() const; - size_t find_internal(size_t start = 0, size_t end = size_t(-1)) const; - size_t peek_tablerow(size_t row) const; - void handle_pending_not(); - void set_table(TableRef tr); - - static bool comp(const std::pair& a, const std::pair& b); - -public: - using HandoverPatch = QueryHandoverPatch; - - std::unique_ptr clone_for_handover(std::unique_ptr& patch, ConstSourcePayload mode) const - { - patch.reset(new HandoverPatch); - return std::make_unique(*this, *patch, mode); - } - - std::unique_ptr clone_for_handover(std::unique_ptr& patch, MutableSourcePayload mode) - { - patch.reset(new HandoverPatch); - return std::make_unique(*this, *patch, mode); - } - - void apply_and_consume_patch(std::unique_ptr& patch, Group& dest_group) - { - apply_patch(*patch, dest_group); - patch.reset(); - } - - void apply_patch(HandoverPatch& patch, Group& dest_group); - Query(const Query& source, HandoverPatch& patch, ConstSourcePayload mode); - Query(Query& source, HandoverPatch& patch, MutableSourcePayload mode); - -private: - void fetch_descriptor(); - - void add_expression_node(std::unique_ptr); - - template - Query& equal(size_t column_ndx1, size_t column_ndx2); - - template - Query& less(size_t column_ndx1, size_t column_ndx2); - - template - Query& less_equal(size_t column_ndx1, size_t column_ndx2); - - template - Query& greater(size_t column_ndx1, size_t column_ndx2); - - template - Query& greater_equal(size_t column_ndx1, size_t column_ndx2); - - template - Query& not_equal(size_t column_ndx1, size_t column_ndx2); - - template - Query& add_condition(size_t column_ndx, T value); - - template - double average(size_t column_ndx, size_t* resultcount = nullptr, size_t start = 0, size_t end = size_t(-1), - size_t limit = size_t(-1)) const; - - template - R aggregate(R (ColClass::*method)(size_t, size_t, size_t, size_t*) const, size_t column_ndx, size_t* resultcount, - size_t start, size_t end, size_t limit, size_t* return_ndx = nullptr) const; - - void aggregate_internal(Action TAction, DataType TSourceColumn, bool nullable, ParentNode* pn, QueryStateBase* st, - size_t start, size_t end, SequentialGetterBase* source_column) const; - - void find_all(TableViewBase& tv, size_t start = 0, size_t end = size_t(-1), size_t limit = size_t(-1)) const; - void delete_nodes() noexcept; - - bool has_conditions() const - { - return m_groups.size() > 0 && m_groups[0].m_root_node; - } - ParentNode* root_node() const - { - REALM_ASSERT(m_groups.size()); - return m_groups[0].m_root_node.get(); - } - - void add_node(std::unique_ptr); - - friend class Table; - friend class TableViewBase; - - std::string error_code; - - std::vector m_groups; - - // Used to access schema while building query: - std::vector m_subtable_path; - - ConstDescriptorRef m_current_descriptor; - TableRef m_table; - - // points to the base class of the restricting view. If the restricting - // view is a link view, m_source_link_view is non-zero. If it is a table view, - // m_source_table_view is non-zero. - RowIndexes* m_view = nullptr; - - // At most one of these can be non-zero, and if so the non-zero one indicates the restricting view. - LinkViewRef m_source_link_view; // link views are refcounted and shared. - TableViewBase* m_source_table_view = nullptr; // table views are not refcounted, and not owned by the query. - std::unique_ptr m_owned_source_table_view; // <--- except when indicated here -}; - -// Implementation: - -inline Query& Query::equal(size_t column_ndx, const char* c_str, bool case_sensitive) -{ - return equal(column_ndx, StringData(c_str), case_sensitive); -} - -inline Query& Query::not_equal(size_t column_ndx, const char* c_str, bool case_sensitive) -{ - return not_equal(column_ndx, StringData(c_str), case_sensitive); -} - -} // namespace realm - -#endif // REALM_QUERY_HPP diff --git a/Example/Pods/Realm/include/core/realm/query_conditions.hpp b/Example/Pods/Realm/include/core/realm/query_conditions.hpp deleted file mode 100644 index dc66d93..0000000 --- a/Example/Pods/Realm/include/core/realm/query_conditions.hpp +++ /dev/null @@ -1,680 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_QUERY_CONDITIONS_HPP -#define REALM_QUERY_CONDITIONS_HPP - -#include -#include - -#include -#include -#include - -namespace realm { - -// Array::VTable only uses the first 4 conditions (enums) in an array of function pointers -enum { cond_Equal, cond_NotEqual, cond_Greater, cond_Less, cond_VTABLE_FINDER_COUNT, cond_None, cond_LeftNotNull }; - -// Quick hack to make "Queries with Integer null columns" able to compile in Visual Studio 2015 which doesn't full -// support sfinae -// (real cause hasn't been investigated yet, cannot exclude that we don't obey c++11 standard) -struct HackClass { - template - bool can_match(A, B, C) - { - REALM_ASSERT(false); - return false; - } - template - bool will_match(A, B, C) - { - REALM_ASSERT(false); - return false; - } -}; - -// Does v2 contain v1? -struct Contains : public HackClass { - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v2.contains(v1); - } - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - return v2.contains(v1); - } - bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const - { - return v2.contains(v1); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool operator()(int64_t, int64_t, bool, bool) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -// Does v2 contain something like v1 (wildcard matching)? -struct Like : public HackClass { - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v2.like(v1); - } - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - return v2.like(v1); - } - bool operator()(BinaryData, BinaryData, bool = false, bool = false) const - { - REALM_ASSERT(false); - return false; - } - - template bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - - template bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - - bool operator()(int64_t, int64_t, bool, bool) const { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -// Does v2 begin with v1? -struct BeginsWith : public HackClass { - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v2.begins_with(v1); - } - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - return v2.begins_with(v1); - } - bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const - { - return v2.begins_with(v1); - } - - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -// Does v2 end with v1? -struct EndsWith : public HackClass { - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v2.ends_with(v1); - } - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - return v2.ends_with(v1); - } - bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const - { - return v2.ends_with(v1); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -struct Equal { - static const int avx = 0x00; // _CMP_EQ_OQ - // bool operator()(const bool v1, const bool v2, bool v1null = false, bool v2null = false) const { return v1 == - // v2; } - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v1 == v2; - } - bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const - { - return v1 == v2; - } - - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - return (v1null && v2null) || (!v1null && !v2null && v1 == v2); - } - static const int condition = cond_Equal; - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - return (v >= lbound && v <= ubound); - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - return (v == 0 && ubound == 0 && lbound == 0); - } -}; - -struct NotEqual { - static const int avx = 0x0B; // _CMP_FALSE_OQ - bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const - { - return v1 != v2; - } - // bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const { return v1 != v2; } - - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - if (!v1null && !v2null) - return v1 != v2; - - if (v1null && v2null) - return false; - - return true; - } - - static const int condition = cond_NotEqual; - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - return !(v == 0 && ubound == 0 && lbound == 0); - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - return (v > ubound || v < lbound); - } - - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } -}; - -// Does v2 contain v1? -struct ContainsIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, - bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - - if (v1.size() == 0 && !v2.is_null()) - return true; - - return search_case_fold(v2, v1_upper, v1_lower, v1.size()) != v2.size(); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - - if (v1.size() == 0 && !v2.is_null()) - return true; - - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return search_case_fold(v2, v1_upper.c_str(), v1_lower.c_str(), v1.size()) != v2.size(); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool operator()(int64_t, int64_t, bool, bool) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -// Does v2 contain something like v1 (wildcard matching)? -struct LikeIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, bool = false) const - { - if (v2.is_null() || v1.is_null()) { - return (v2.is_null() && v1.is_null()); - } - - return string_like_ins(v2, v1_lower, v1_upper); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v2.is_null() || v1.is_null()) { - return (v2.is_null() && v1.is_null()); - } - - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return string_like_ins(v2, v1_lower, v1_upper); - } - - template bool operator()(A, B) const { REALM_ASSERT(false); return false; } - template bool operator()(A, B, C, D) const { REALM_ASSERT(false); return false; } - bool operator()(int64_t, int64_t, bool, bool) const { REALM_ASSERT(false); return false; } - - static const int condition = -1; -}; - -// Does v2 begin with v1? -struct BeginsWithIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, - bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - return v1.size() <= v2.size() && equal_case_fold(v2.prefix(v1.size()), v1_upper, v1_lower); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - - if (v1.size() > v2.size()) - return false; - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return equal_case_fold(v2.prefix(v1.size()), v1_upper.c_str(), v1_lower.c_str()); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool operator()(int64_t, int64_t, bool, bool) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -// Does v2 end with v1? -struct EndsWithIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, - bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - - return v1.size() <= v2.size() && equal_case_fold(v2.suffix(v1.size()), v1_upper, v1_lower); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v2.is_null() && !v1.is_null()) - return false; - - if (v1.size() > v2.size()) - return false; - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return equal_case_fold(v2.suffix(v1.size()), v1_upper.c_str(), v1_lower.c_str()); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool operator()(int64_t, int64_t, bool, bool) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -struct EqualIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, - bool = false) const - { - if (v1.is_null() != v2.is_null()) - return false; - - return v1.size() == v2.size() && equal_case_fold(v2, v1_upper, v1_lower); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v1.is_null() != v2.is_null()) - return false; - - if (v1.size() != v2.size()) - return false; - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return equal_case_fold(v2, v1_upper.c_str(), v1_lower.c_str()); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool operator()(int64_t, int64_t, bool, bool) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -struct NotEqualIns : public HackClass { - bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, - bool = false) const - { - if (v1.is_null() != v2.is_null()) - return true; - return v1.size() != v2.size() || !equal_case_fold(v2, v1_upper, v1_lower); - } - - // Slow version, used if caller hasn't stored an upper and lower case version - bool operator()(StringData v1, StringData v2, bool = false, bool = false) const - { - if (v1.is_null() != v2.is_null()) - return true; - - if (v1.size() != v2.size()) - return true; - std::string v1_upper = case_map(v1, true, IgnoreErrors); - std::string v1_lower = case_map(v1, false, IgnoreErrors); - return !equal_case_fold(v2, v1_upper.c_str(), v1_lower.c_str()); - } - - template - bool operator()(A, B) const - { - REALM_ASSERT(false); - return false; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - - static const int condition = -1; -}; - -struct Greater { - static const int avx = 0x1E; // _CMP_GT_OQ - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - if (v1null || v2null) - return false; - - return v1 > v2; - } - static const int condition = cond_Greater; - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - return ubound > v; - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(ubound); - return lbound > v; - } -}; - -struct None { - template - bool operator()(const T&, const T&, bool = false, bool = false) const - { - return true; - } - static const int condition = cond_None; - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - static_cast(ubound); - static_cast(v); - return true; - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - static_cast(ubound); - static_cast(v); - return true; - } -}; - -struct NotNull { - template - bool operator()(const T&, const T&, bool v = false, bool = false) const - { - return !v; - } - static const int condition = cond_LeftNotNull; - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - static_cast(ubound); - static_cast(v); - return true; - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - static_cast(ubound); - static_cast(v); - return true; - } -}; - - -struct Less { - static const int avx = 0x11; // _CMP_LT_OQ - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - if (v1null || v2null) - return false; - - return v1 < v2; - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - static const int condition = cond_Less; - bool can_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(ubound); - return lbound < v; - } - bool will_match(int64_t v, int64_t lbound, int64_t ubound) - { - static_cast(lbound); - return ubound < v; - } -}; - -struct LessEqual : public HackClass { - static const int avx = 0x12; // _CMP_LE_OQ - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - if (v1null && v2null) - return true; - - return (!v1null && !v2null && v1 <= v2); - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - static const int condition = -1; -}; - -struct GreaterEqual : public HackClass { - static const int avx = 0x1D; // _CMP_GE_OQ - template - bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const - { - if (v1null && v2null) - return true; - - return (!v1null && !v2null && v1 >= v2); - } - template - bool operator()(A, B, C, D) const - { - REALM_ASSERT(false); - return false; - } - static const int condition = -1; -}; - - -// CompareLess is a temporary hack to have a generalized way to compare any realm types. Todo, enable correct < -// operator of StringData (currently gives circular header dependency with utf8.hpp) -template -struct CompareLess { - static bool compare(T v1, T v2, bool = false, bool = false) - { - return v1 < v2; - } -}; -template <> -struct CompareLess { - static bool compare(StringData v1, StringData v2, bool = false, bool = false) - { - bool ret = utf8_compare(v1.data(), v2.data()); - return ret; - } -}; - -} // namespace realm - -#endif // REALM_QUERY_CONDITIONS_HPP diff --git a/Example/Pods/Realm/include/core/realm/query_engine.hpp b/Example/Pods/Realm/include/core/realm/query_engine.hpp deleted file mode 100644 index c0cc7db..0000000 --- a/Example/Pods/Realm/include/core/realm/query_engine.hpp +++ /dev/null @@ -1,1840 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -/* -A query consists of node objects, one for each query condition. Each node contains pointers to all other nodes: - -node1 node2 node3 ------- ----- ----- -node2* node1* node1* -node3* node3* node2* - -The construction of all this takes part in query.cpp. Each node has two important functions: - - aggregate(start, end) - aggregate_local(start, end) - -The aggregate() function executes the aggregate of a query. You can call the method on any of the nodes -(except children nodes of OrNode and SubtableNode) - it has the same behaviour. The function contains -scheduling that calls aggregate_local(start, end) on different nodes with different start/end ranges, -depending on what it finds is most optimal. - -The aggregate_local() function contains a tight loop that tests the condition of its own node, and upon match -it tests all other conditions at that index to report a full match or not. It will remain in the tight loop -after a full match. - -So a call stack with 2 and 9 being local matches of a node could look like this: - -aggregate(0, 10) - node1->aggregate_local(0, 3) - node2->find_first_local(2, 3) - node3->find_first_local(2, 3) - node3->aggregate_local(3, 10) - node1->find_first_local(4, 5) - node2->find_first_local(4, 5) - node1->find_first_local(7, 8) - node2->find_first_local(7, 8) - -find_first_local(n, n + 1) is a function that can be used to test a single row of another condition. Note that -this is very simplified. There are other statistical arguments to the methods, and also, find_first_local() can be -called from a callback function called by an integer Array. - - -Template arguments in methods: ----------------------------------------------------------------------------------------------------- - -TConditionFunction: Each node has a condition from query_conditions.c such as Equal, GreaterEqual, etc - -TConditionValue: Type of values in condition column. That is, int64_t, float, int, bool, etc - -TAction: What to do with each search result, from the enums act_ReturnFirst, act_Count, act_Sum, etc - -TResult: Type of result of actions - float, double, int64_t, etc. Special notes: For act_Count it's - int64_t, for RLM_FIND_ALL it's int64_t which points at destination array. - -TSourceColumn: Type of source column used in actions, or *ignored* if no source column is used (like for - act_Count, act_ReturnFirst) - - -There are two important classes used in queries: ----------------------------------------------------------------------------------------------------- -SequentialGetter Column iterator used to get successive values with leaf caching. Used both for condition columns - and aggregate source column - -AggregateState State of the aggregate - contains a state variable that stores intermediate sum, max, min, - etc, etc. - -*/ - -#ifndef REALM_QUERY_ENGINE_HPP -#define REALM_QUERY_ENGINE_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 -#include -#endif - -namespace realm { - -// Number of matches to find in best condition loop before breaking out to probe other conditions. Too low value gives -// too many constant time overheads everywhere in the query engine. Too high value makes it adapt less rapidly to -// changes in match frequencies. -const size_t findlocals = 64; - -// Average match distance in linear searches where further increase in distance no longer increases query speed -// (because time spent on handling each match becomes insignificant compared to time spent on the search). -const size_t bestdist = 512; - -// Minimum number of matches required in a certain condition before it can be used to compute statistics. Too high -// value can spent too much time in a bad node (with high match frequency). Too low value gives inaccurate statistics. -const size_t probe_matches = 4; - -const size_t bitwidth_time_unit = 64; - -typedef bool (*CallbackDummy)(int64_t); - - -class ParentNode { - typedef ParentNode ThisType; - -public: - ParentNode() = default; - virtual ~ParentNode() = default; - - void gather_children(std::vector& v) - { - m_children.clear(); - size_t i = v.size(); - v.push_back(this); - - if (m_child) - m_child->gather_children(v); - - m_children = v; - m_children.erase(m_children.begin() + i); - m_children.insert(m_children.begin(), this); - } - - double cost() const - { - return 8 * bitwidth_time_unit / m_dD + - m_dT; // dt = 1/64 to 1. Match dist is 8 times more important than bitwidth - } - - size_t find_first(size_t start, size_t end); - - virtual void init() - { - if (m_child) - m_child->init(); - m_column_action_specializer = nullptr; - } - - void set_table(const Table& table) - { - if (&table == m_table) - return; - - m_table.reset(&table); - if (m_child) - m_child->set_table(table); - table_changed(); - } - - virtual size_t find_first_local(size_t start, size_t end) = 0; - - virtual void aggregate_local_prepare(Action TAction, DataType col_id, bool nullable); - - template - bool column_action_specialization(QueryStateBase* st, SequentialGetterBase* source_column, size_t r) - { - // TResult: type of query result - // TSourceValue: type of aggregate source - using TSourceValue = typename TSourceColumn::value_type; - using TResult = typename ColumnTypeTraitsSum::sum_type; - - // Sum of float column must accumulate in double - static_assert(!(TAction == act_Sum && - (std::is_same::value && !std::is_same::value)), - ""); - - TSourceValue av{}; - // uses_val test because compiler cannot see that IntegerColumn::get has no side effect and result is - // discarded - if (static_cast*>(st)->template uses_val() && source_column != nullptr) { - REALM_ASSERT_DEBUG(dynamic_cast*>(source_column) != nullptr); - av = static_cast*>(source_column)->get_next(r); - } - REALM_ASSERT_DEBUG(dynamic_cast*>(st) != nullptr); - bool cont = static_cast*>(st)->template match(r, 0, av); - return cont; - } - - virtual size_t aggregate_local(QueryStateBase* st, size_t start, size_t end, size_t local_limit, - SequentialGetterBase* source_column); - - - virtual std::string validate() - { - if (error_code != "") - return error_code; - if (m_child == nullptr) - return ""; - else - return m_child->validate(); - } - - ParentNode(const ParentNode& from) - : ParentNode(from, nullptr) - { - } - - ParentNode(const ParentNode& from, QueryNodeHandoverPatches* patches) - : m_child(from.m_child ? from.m_child->clone(patches) : nullptr) - , m_condition_column_idx(from.m_condition_column_idx) - , m_dD(from.m_dD) - , m_dT(from.m_dT) - , m_probes(from.m_probes) - , m_matches(from.m_matches) - , m_table(patches ? ConstTableRef{} : from.m_table) - { - } - - void add_child(std::unique_ptr child) - { - if (m_child) - m_child->add_child(std::move(child)); - else - m_child = std::move(child); - } - - virtual std::unique_ptr clone(QueryNodeHandoverPatches* = nullptr) const = 0; - - virtual void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) - { - if (m_child) - m_child->apply_handover_patch(patches, group); - } - - std::unique_ptr m_child; - std::vector m_children; - size_t m_condition_column_idx = npos; // Column of search criteria - - double m_dD; // Average row distance between each local match at current position - double m_dT = 0.0; // Time overhead of testing index i + 1 if we have just tested index i. > 1 for linear scans, 0 - // for index/tableview - - size_t m_probes = 0; - size_t m_matches = 0; - -protected: - typedef bool (ParentNode::*Column_action_specialized)(QueryStateBase*, SequentialGetterBase*, size_t); - Column_action_specialized m_column_action_specializer; - ConstTableRef m_table; - std::string error_code; - - const ColumnBase& get_column_base(size_t ndx) - { - return m_table->get_column_base(ndx); - } - - template - const ColType& get_column(size_t ndx) - { - auto& col = m_table->get_column_base(ndx); - REALM_ASSERT_DEBUG(dynamic_cast(&col)); - return static_cast(col); - } - - ColumnType get_real_column_type(size_t ndx) - { - return m_table->get_real_column_type(ndx); - } - - template - void copy_getter(SequentialGetter& dst, size_t& dst_idx, const SequentialGetter& src, - const QueryNodeHandoverPatches* patches) - { - if (src.m_column) { - if (patches) - dst_idx = src.m_column->get_column_index(); - else - dst.init(src.m_column); - } - } - -private: - virtual void table_changed() = 0; -}; - -// For conditions on a subtable (encapsulated in subtable()...end_subtable()). These return the parent row as match if -// and -// only if one or more subtable rows match the condition. -class SubtableNode : public ParentNode { -public: - SubtableNode(size_t column, std::unique_ptr condition) - : m_condition(std::move(condition)) - { - m_dT = 100.0; - m_condition_column_idx = column; - } - - void init() override - { - m_dD = 10.0; - - // m_condition is first node in condition of subtable query. - if (m_condition) { - // Can't call init() here as usual since the subtable can be degenerate - // m_condition->init(table); - std::vector v; - m_condition->gather_children(v); - } - - // m_child is next node of parent query - if (m_child) - m_child->init(); - } - - void table_changed() override - { - m_col_type = m_table->get_real_column_type(m_condition_column_idx); - REALM_ASSERT(m_col_type == col_type_Table || m_col_type == col_type_Mixed); - if (m_col_type == col_type_Table) - m_column = &m_table->get_column_table(m_condition_column_idx); - else // Mixed - m_column = &m_table->get_column_mixed(m_condition_column_idx); - } - - std::string validate() override - { - if (error_code != "") - return error_code; - if (m_condition == nullptr) - return "Unbalanced subtable/end_subtable block"; - else - return m_condition->validate(); - } - - size_t find_first_local(size_t start, size_t end) override - { - REALM_ASSERT(m_table); - REALM_ASSERT(m_condition); - - for (size_t s = start; s < end; ++s) { - const Table* subtable; - if (m_col_type == col_type_Table) - subtable = static_cast(m_column)->get_subtable_ptr(s); - else { - subtable = static_cast(m_column)->get_subtable_ptr(s); - if (!subtable) - continue; - } - - if (subtable->is_degenerate()) - return not_found; - - m_condition->set_table(*subtable); - m_condition->init(); - const size_t subsize = subtable->size(); - const size_t sub = m_condition->find_first(0, subsize); - - if (sub != not_found) - return s; - } - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new SubtableNode(*this, patches)); - } - - SubtableNode(const SubtableNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_condition(from.m_condition ? from.m_condition->clone(patches) : nullptr) - , m_column(from.m_column) - , m_col_type(from.m_col_type) - { - if (m_column && patches) - m_condition_column_idx = m_column->get_column_index(); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_condition->apply_handover_patch(patches, group); - ParentNode::apply_handover_patch(patches, group); - } - - std::unique_ptr m_condition; - const ColumnBase* m_column = nullptr; - ColumnType m_col_type; -}; - -namespace _impl { - -template -struct CostHeuristic; - -template <> -struct CostHeuristic { - static constexpr double dD() - { - return 100.0; - } - static constexpr double dT() - { - return 1.0 / 4.0; - } -}; - -template <> -struct CostHeuristic { - static constexpr double dD() - { - return 100.0; - } - static constexpr double dT() - { - return 1.0 / 4.0; - } -}; - -// FIXME: Add AdaptiveStringColumn, BasicColumn, etc. -} - -class ColumnNodeBase : public ParentNode { -protected: - ColumnNodeBase(size_t column_idx) - { - m_condition_column_idx = column_idx; - } - - ColumnNodeBase(const ColumnNodeBase& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_last_local_match(from.m_last_local_match) - , m_local_matches(from.m_local_matches) - , m_local_limit(from.m_local_limit) - , m_fastmode_disabled(from.m_fastmode_disabled) - , m_action(from.m_action) - , m_state(from.m_state) - , m_source_column(from.m_source_column) - { - } - - template - bool match_callback(int64_t v) - { - using TSourceValue = typename ColType::value_type; - using QueryStateType = typename ColumnTypeTraitsSum::sum_type; - - size_t i = to_size_t(v); - m_last_local_match = i; - m_local_matches++; - - auto state = static_cast*>(m_state); - auto source_column = static_cast*>(m_source_column); - - // Test remaining sub conditions of this node. m_children[0] is the node that called match_callback(), so skip - // it - for (size_t c = 1; c < m_children.size(); c++) { - m_children[c]->m_probes++; - size_t m = m_children[c]->find_first_local(i, i + 1); - if (m != i) - return true; - } - - bool b; - if (state->template uses_val()) { // Compiler cannot see that IntegerColumn::Get has no side effect - // and result is discarded - TSourceValue av = source_column->get_next(i); - b = state->template match(i, 0, av); - } - else { - b = state->template match(i, 0, TSourceValue{}); - } - - return b; - } - - // Aggregate bookkeeping - size_t m_last_local_match = npos; - size_t m_local_matches = 0; - size_t m_local_limit = 0; - bool m_fastmode_disabled = false; - Action m_action; - QueryStateBase* m_state = nullptr; - SequentialGetterBase* m_source_column = - nullptr; // Column of values used in aggregate (act_FindAll, actReturnFirst, act_Sum, etc) -}; - -template -class IntegerNodeBase : public ColumnNodeBase { - using ThisType = IntegerNodeBase; - -public: - using TConditionValue = typename ColType::value_type; - static const bool nullable = ColType::nullable; - - template - bool find_callback_specialization(size_t s, size_t end_in_leaf) - { - using AggregateColumnType = typename GetColumnType::type; - bool cont; - size_t start_in_leaf = s - this->m_leaf_start; - cont = this->m_leaf_ptr->template find( - m_value, start_in_leaf, end_in_leaf, this->m_leaf_start, nullptr, - std::bind(std::mem_fn(&ThisType::template match_callback), this, - std::placeholders::_1)); - return cont; - } - -protected: - using LeafType = typename ColType::LeafType; - using LeafInfo = typename ColType::LeafInfo; - - size_t aggregate_local_impl(QueryStateBase* st, size_t start, size_t end, size_t local_limit, - SequentialGetterBase* source_column, int c) - { - REALM_ASSERT(m_children.size() > 0); - m_local_matches = 0; - m_local_limit = local_limit; - m_last_local_match = start - 1; - m_state = st; - - // If there are no other nodes than us (m_children.size() == 1) AND the column used for our condition is - // the same as the column used for the aggregate action, then the entire query can run within scope of that - // column only, with no references to other columns: - bool fastmode = should_run_in_fastmode(source_column); - for (size_t s = start; s < end;) { - cache_leaf(s); - - size_t end_in_leaf; - if (end > m_leaf_end) - end_in_leaf = m_leaf_end - m_leaf_start; - else - end_in_leaf = end - m_leaf_start; - - if (fastmode) { - bool cont; - size_t start_in_leaf = s - m_leaf_start; - cont = m_leaf_ptr->find(c, m_action, m_value, start_in_leaf, end_in_leaf, m_leaf_start, - static_cast*>(st)); - if (!cont) - return not_found; - } - // Else, for each match in this node, call our IntegerNodeBase::match_callback to test remaining nodes - // and/or extract - // aggregate payload from aggregate column: - else { - m_source_column = source_column; - bool cont = (this->*m_find_callback_specialized)(s, end_in_leaf); - if (!cont) - return not_found; - } - - if (m_local_matches == m_local_limit) - break; - - s = end_in_leaf + m_leaf_start; - } - - if (m_local_matches == m_local_limit) { - m_dD = (m_last_local_match + 1 - start) / (m_local_matches + 1.0); - return m_last_local_match + 1; - } - else { - m_dD = (end - start) / (m_local_matches + 1.0); - return end; - } - } - - IntegerNodeBase(TConditionValue value, size_t column_idx) - : ColumnNodeBase(column_idx) - , m_value(std::move(value)) - { - } - - IntegerNodeBase(const ThisType& from, QueryNodeHandoverPatches* patches) - : ColumnNodeBase(from, patches) - , m_value(from.m_value) - , m_condition_column(from.m_condition_column) - , m_find_callback_specialized(from.m_find_callback_specialized) - { - if (m_condition_column && patches) - m_condition_column_idx = m_condition_column->get_column_index(); - } - - void table_changed() override - { - m_condition_column = &get_column(m_condition_column_idx); - } - - void init() override - { - ColumnNodeBase::init(); - - m_dT = _impl::CostHeuristic::dT(); - m_dD = _impl::CostHeuristic::dD(); - - // Clear leaf cache - m_leaf_end = 0; - m_array_ptr.reset(); // Explicitly destroy the old one first, because we're reusing the memory. - m_array_ptr.reset(new (&m_leaf_cache_storage) LeafType(m_table->get_alloc())); - - if (m_child) - m_child->init(); - } - - void get_leaf(const ColType& col, size_t ndx) - { - size_t ndx_in_leaf; - LeafInfo leaf_info{&m_leaf_ptr, m_array_ptr.get()}; - col.get_leaf(ndx, ndx_in_leaf, leaf_info); - m_leaf_start = ndx - ndx_in_leaf; - m_leaf_end = m_leaf_start + m_leaf_ptr->size(); - } - - void cache_leaf(size_t s) - { - if (s >= m_leaf_end || s < m_leaf_start) { - get_leaf(*m_condition_column, s); - size_t w = m_leaf_ptr->get_width(); - m_dT = (w == 0 ? 1.0 / REALM_MAX_BPNODE_SIZE : w / float(bitwidth_time_unit)); - } - } - - bool should_run_in_fastmode(SequentialGetterBase* source_column) const - { - return (m_children.size() == 1 && - (source_column == nullptr || - (!m_fastmode_disabled && - static_cast*>(source_column)->m_column == m_condition_column))); - } - - // Search value: - TConditionValue m_value; - - // Column on which search criteria are applied - const ColType* m_condition_column = nullptr; - - // Leaf cache - using LeafCacheStorage = typename std::aligned_storage::type; - LeafCacheStorage m_leaf_cache_storage; - std::unique_ptr m_array_ptr; - const LeafType* m_leaf_ptr = nullptr; - size_t m_leaf_start = npos; - size_t m_leaf_end = 0; - size_t m_local_end; - - // Aggregate optimization - using TFind_callback_specialized = bool (ThisType::*)(size_t, size_t); - TFind_callback_specialized m_find_callback_specialized = nullptr; -}; - -// FIXME: Add specialization that uses index for TConditionFunction = Equal -template -class IntegerNode : public IntegerNodeBase { - using BaseType = IntegerNodeBase; - using ThisType = IntegerNode; - -public: - static const bool special_null_node = false; - using TConditionValue = typename BaseType::TConditionValue; - - IntegerNode(TConditionValue value, size_t column_ndx) - : BaseType(value, column_ndx) - { - } - IntegerNode(const IntegerNode& from, QueryNodeHandoverPatches* patches) - : BaseType(from, patches) - { - } - - void aggregate_local_prepare(Action action, DataType col_id, bool nullable) override - { - this->m_fastmode_disabled = (col_id == type_Float || col_id == type_Double); - this->m_action = action; - this->m_find_callback_specialized = get_specialized_callback(action, col_id, nullable); - } - - size_t aggregate_local(QueryStateBase* st, size_t start, size_t end, size_t local_limit, - SequentialGetterBase* source_column) override - { - constexpr int cond = TConditionFunction::condition; - return this->aggregate_local_impl(st, start, end, local_limit, source_column, cond); - } - - size_t find_first_local(size_t start, size_t end) override - { - REALM_ASSERT(this->m_table); - - while (start < end) { - - // Cache internal leaves - if (start >= this->m_leaf_end || start < this->m_leaf_start) { - this->get_leaf(*this->m_condition_column, start); - } - - // FIXME: Create a fast bypass when you just need to check 1 row, which is used alot from within core. - // It should just call array::get and save the initial overhead of find_first() which has become quite - // big. Do this when we have cleaned up core a bit more. - - size_t end2; - if (end > this->m_leaf_end) - end2 = this->m_leaf_end - this->m_leaf_start; - else - end2 = end - this->m_leaf_start; - - size_t s; - s = this->m_leaf_ptr->template find_first(this->m_value, start - this->m_leaf_start, - end2); - - if (s == not_found) { - start = this->m_leaf_end; - continue; - } - else - return s + this->m_leaf_start; - } - - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new IntegerNode(*this, patches)); - } - -protected: - using TFind_callback_specialized = typename BaseType::TFind_callback_specialized; - - static TFind_callback_specialized get_specialized_callback(Action action, DataType col_id, bool nullable) - { - switch (action) { - case act_Count: - return get_specialized_callback_2_int(col_id, nullable); - case act_Sum: - return get_specialized_callback_2(col_id, nullable); - case act_Max: - return get_specialized_callback_2(col_id, nullable); - case act_Min: - return get_specialized_callback_2(col_id, nullable); - case act_FindAll: - return get_specialized_callback_2_int(col_id, nullable); - case act_CallbackIdx: - return get_specialized_callback_2_int(col_id, nullable); - default: - break; - } - REALM_ASSERT(false); // Invalid aggregate function - return nullptr; - } - - template - static TFind_callback_specialized get_specialized_callback_2(DataType col_id, bool nullable) - { - switch (col_id) { - case type_Int: - return get_specialized_callback_3(nullable); - case type_Float: - return get_specialized_callback_3(nullable); - case type_Double: - return get_specialized_callback_3(nullable); - default: - break; - } - REALM_ASSERT(false); // Invalid aggregate source column - return nullptr; - } - - template - static TFind_callback_specialized get_specialized_callback_2_int(DataType col_id, bool nullable) - { - if (col_id == type_Int) { - return get_specialized_callback_3(nullable); - } - REALM_ASSERT(false); // Invalid aggregate source column - return nullptr; - } - - template - static TFind_callback_specialized get_specialized_callback_3(bool nullable) - { - if (nullable) { - return &BaseType::template find_callback_specialization; - } - else { - return &BaseType::template find_callback_specialization; - } - } -}; - -// This node is currently used for floats and doubles only -template -class FloatDoubleNode : public ParentNode { -public: - using TConditionValue = typename ColType::value_type; - static const bool special_null_node = false; - - FloatDoubleNode(TConditionValue v, size_t column_ndx) - : m_value(v) - { - m_condition_column_idx = column_ndx; - m_dT = 1.0; - } - FloatDoubleNode(null, size_t column_ndx) - : m_value(null::get_null_float()) - { - m_condition_column_idx = column_ndx; - m_dT = 1.0; - } - - void table_changed() override - { - m_condition_column.init(&get_column(m_condition_column_idx)); - } - - void init() override - { - ParentNode::init(); - m_dD = 100.0; - } - - size_t find_first_local(size_t start, size_t end) override - { - TConditionFunction cond; - - auto find = [&](bool nullability) { - bool m_value_nan = nullability ? null::is_null_float(m_value) : false; - for (size_t s = start; s < end; ++s) { - TConditionValue v = m_condition_column.get_next(s); - REALM_ASSERT(!(null::is_null_float(v) && !nullability)); - if (cond(v, m_value, nullability ? null::is_null_float(v) : false, m_value_nan)) - return s; - } - return not_found; - }; - - // This will inline the second case but no the first. Todo, use templated lambda when switching to c++14 - if (m_table->is_nullable(m_condition_column_idx)) - return find(true); - else - return find(false); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new FloatDoubleNode(*this, patches)); - } - - FloatDoubleNode(const FloatDoubleNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_value(from.m_value) - { - copy_getter(m_condition_column, m_condition_column_idx, from.m_condition_column, patches); - } - -protected: - TConditionValue m_value; - SequentialGetter m_condition_column; -}; - - -template -class BinaryNode : public ParentNode { -public: - using TConditionValue = BinaryData; - static const bool special_null_node = false; - - BinaryNode(BinaryData v, size_t column) - : m_value(v) - { - m_dT = 100.0; - m_condition_column_idx = column; - } - - BinaryNode(null, size_t column) - : BinaryNode(BinaryData{}, column) - { - } - - void table_changed() override - { - m_condition_column = &get_column(m_condition_column_idx); - } - - void init() override - { - m_dD = 100.0; - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override - { - TConditionFunction condition; - for (size_t s = start; s < end; ++s) { - BinaryData value = m_condition_column->get(s); - if (condition(m_value.get(), value)) - return s; - } - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new BinaryNode(*this, patches)); - } - - BinaryNode(const BinaryNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_value(from.m_value) - , m_condition_column(from.m_condition_column) - { - if (m_condition_column && patches) - m_condition_column_idx = m_condition_column->get_column_index(); - } - -private: - OwnedBinaryData m_value; - const BinaryColumn* m_condition_column; -}; - - -template -class TimestampNode : public ParentNode { -public: - using TConditionValue = Timestamp; - static const bool special_null_node = false; - - TimestampNode(Timestamp v, size_t column) - : m_value(v) - { - m_condition_column_idx = column; - } - - TimestampNode(null, size_t column) - : TimestampNode(Timestamp{}, column) - { - } - - void table_changed() override - { - m_condition_column = &get_column(m_condition_column_idx); - } - - void init() override - { - m_dD = 100.0; - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override - { - size_t ret = m_condition_column->find(m_value, start, end); - return ret; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new TimestampNode(*this, patches)); - } - - TimestampNode(const TimestampNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_value(from.m_value) - , m_condition_column(from.m_condition_column) - { - if (m_condition_column && patches) - m_condition_column_idx = m_condition_column->get_column_index(); - } - -private: - Timestamp m_value; - const TimestampColumn* m_condition_column; -}; - -class StringNodeBase : public ParentNode { -public: - using TConditionValue = StringData; - static const bool special_null_node = true; - - StringNodeBase(StringData v, size_t column) - : m_value(v.is_null() ? util::none : util::make_optional(std::string(v))) - { - m_condition_column_idx = column; - } - - void table_changed() override - { - m_condition_column = &get_column_base(m_condition_column_idx); - m_column_type = get_real_column_type(m_condition_column_idx); - } - - void init() override - { - m_dT = 10.0; - m_probes = 0; - m_matches = 0; - m_end_s = 0; - m_leaf_start = 0; - m_leaf_end = 0; - } - - void clear_leaf_state() - { - m_leaf.reset(nullptr); - } - - StringNodeBase(const StringNodeBase& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_value(from.m_value) - , m_condition_column(from.m_condition_column) - , m_column_type(from.m_column_type) - , m_leaf_type(from.m_leaf_type) - { - if (m_condition_column && patches) - m_condition_column_idx = m_condition_column->get_column_index(); - } - -protected: - util::Optional m_value; - - const ColumnBase* m_condition_column = nullptr; - ColumnType m_column_type; - - // Used for linear scan through short/long-string - std::unique_ptr m_leaf; - StringColumn::LeafType m_leaf_type; - size_t m_end_s = 0; - size_t m_leaf_start = 0; - size_t m_leaf_end = 0; -}; - -// Conditions for strings. Note that Equal is specialized later in this file! -template -class StringNode : public StringNodeBase { -public: - StringNode(StringData v, size_t column) - : StringNodeBase(v, column) - { - auto upper = case_map(v, true); - auto lower = case_map(v, false); - if (!upper || !lower) { - error_code = "Malformed UTF-8: " + std::string(v); - } - else { - m_ucase = std::move(*upper); - m_lcase = std::move(*lower); - } - } - - void init() override - { - clear_leaf_state(); - - m_dD = 100.0; - - StringNodeBase::init(); - - if (m_child) - m_child->init(); - } - - - size_t find_first_local(size_t start, size_t end) override - { - TConditionFunction cond; - - for (size_t s = start; s < end; ++s) { - StringData t; - - if (m_column_type == col_type_StringEnum) { - // enum - t = static_cast(m_condition_column)->get(s); - } - else { - // short or long - const StringColumn* asc = static_cast(m_condition_column); - REALM_ASSERT_3(s, <, asc->size()); - if (s >= m_end_s || s < m_leaf_start) { - // we exceeded current leaf's range - clear_leaf_state(); - size_t ndx_in_leaf; - m_leaf = asc->get_leaf(s, ndx_in_leaf, m_leaf_type); - m_leaf_start = s - ndx_in_leaf; - - if (m_leaf_type == StringColumn::leaf_type_Small) - m_end_s = m_leaf_start + static_cast(*m_leaf).size(); - else if (m_leaf_type == StringColumn::leaf_type_Medium) - m_end_s = m_leaf_start + static_cast(*m_leaf).size(); - else - m_end_s = m_leaf_start + static_cast(*m_leaf).size(); - } - - if (m_leaf_type == StringColumn::leaf_type_Small) - t = static_cast(*m_leaf).get(s - m_leaf_start); - else if (m_leaf_type == StringColumn::leaf_type_Medium) - t = static_cast(*m_leaf).get(s - m_leaf_start); - else - t = static_cast(*m_leaf).get_string(s - m_leaf_start); - } - if (cond(StringData(m_value), m_ucase.data(), m_lcase.data(), t)) - return s; - } - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new StringNode(*this, patches)); - } - - StringNode(const StringNode& from, QueryNodeHandoverPatches* patches) - : StringNodeBase(from, patches) - , m_ucase(from.m_ucase) - , m_lcase(from.m_lcase) - { - } - -protected: - std::string m_ucase; - std::string m_lcase; -}; - - -// Specialization for Equal condition on Strings - we specialize because we can utilize indexes (if they exist) for -// Equal. -// Future optimization: make specialization for greater, notequal, etc -template <> -class StringNode : public StringNodeBase { -public: - StringNode(StringData v, size_t column) - : StringNodeBase(v, column) - { - } - ~StringNode() noexcept override - { - deallocate(); - } - - void deallocate() noexcept - { - // Must be called after each query execution too free temporary resources used by the execution. Run in - // destructor, but also in Init because a user could define a query once and execute it multiple times. - clear_leaf_state(); - - if (m_index_matches_destroy) - m_index_matches->destroy(); - - m_index_matches_destroy = false; - m_index_matches.reset(); - m_index_getter.reset(); - } - - void init() override - { - deallocate(); - m_dD = 10.0; - StringNodeBase::init(); - - if (m_column_type == col_type_StringEnum) { - m_dT = 1.0; - m_key_ndx = static_cast(m_condition_column)->get_key_ndx(m_value); - } - else if (m_condition_column->has_search_index()) { - m_dT = 0.0; - } - else { - m_dT = 10.0; - } - - if (m_condition_column->has_search_index()) { - FindRes fr; - InternalFindResult res; - - if (m_column_type == col_type_StringEnum) { - fr = static_cast(m_condition_column)->find_all_no_copy(m_value, res); - } - else { - fr = static_cast(m_condition_column)->find_all_no_copy(m_value, res); - } - - m_index_matches_destroy = false; - m_last_start = size_t(-1); - - switch (fr) { - case FindRes_single: - m_index_matches.reset( - new IntegerColumn(IntegerColumn::unattached_root_tag(), Allocator::get_default())); // Throws - m_index_matches->get_root_array()->create(Array::type_Normal); // Throws - m_index_matches->add(res.payload); - m_index_matches_destroy = true; // we own m_index_matches, so we must destroy it - m_results_start = 0; - m_results_end = 1; - break; - case FindRes_column: - // todo: Apparently we can't use m_index.get_alloc() because it uses default allocator which - // simply makes - // translate(x) = x. Shouldn't it inherit owner column's allocator?! - m_index_matches.reset(new IntegerColumn(m_condition_column->get_alloc(), res.payload)); // Throws - m_results_start = res.start_ndx; - m_results_end = res.end_ndx; - - // FIXME: handle start and end of find_result! - break; - case FindRes_not_found: - m_index_matches.reset(); - m_index_getter.reset(); - break; - } - - if (m_index_matches) { - m_index_getter.reset(new SequentialGetter(m_index_matches.get())); - } - } - else if (m_column_type != col_type_String) { - REALM_ASSERT_DEBUG(dynamic_cast(m_condition_column)); - m_cse.init(static_cast(m_condition_column)); - } - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override - { - REALM_ASSERT(m_table); - - if (m_condition_column->has_search_index()) { - // Indexed string column - if (!m_index_getter) - return not_found; // no matches in the index - - if (m_last_start > start) - m_last_indexed = m_results_start; - m_last_start = start; - - while (m_last_indexed < m_results_end) { - m_index_getter->cache_next(m_last_indexed); - size_t f = m_index_getter->m_leaf_ptr->find_gte(start, m_last_indexed - m_index_getter->m_leaf_start, - m_results_end - m_index_getter->m_leaf_start); - - if (f == not_found) { - // Not found in this leaf - move on to next - m_last_indexed = m_index_getter->m_leaf_end; - } - else if (f >= (m_results_end - m_index_getter->m_leaf_start)) { - // Found outside valid range - return not_found; - } - else { - size_t found_index = to_size_t(m_index_getter->m_leaf_ptr->get(f)); - if (found_index >= end) - return not_found; - else { - m_last_indexed = f + m_index_getter->m_leaf_start; - return found_index; - } - } - } - return not_found; - } - - if (m_column_type != col_type_String) { - // Enum string column - if (m_key_ndx == not_found) - return not_found; // not in key set - - for (size_t s = start; s < end; ++s) { - m_cse.cache_next(s); - s = m_cse.m_leaf_ptr->find_first(m_key_ndx, s - m_cse.m_leaf_start, m_cse.local_end(end)); - if (s == not_found) - s = m_cse.m_leaf_end - 1; - else - return s + m_cse.m_leaf_start; - } - - return not_found; - } - - // Normal string column, with long or short leaf - for (size_t s = start; s < end; ++s) { - const StringColumn* asc = static_cast(m_condition_column); - if (s >= m_leaf_end || s < m_leaf_start) { - clear_leaf_state(); - size_t ndx_in_leaf; - m_leaf = asc->get_leaf(s, ndx_in_leaf, m_leaf_type); - m_leaf_start = s - ndx_in_leaf; - if (m_leaf_type == StringColumn::leaf_type_Small) - m_leaf_end = m_leaf_start + static_cast(*m_leaf).size(); - else if (m_leaf_type == StringColumn::leaf_type_Medium) - m_leaf_end = m_leaf_start + static_cast(*m_leaf).size(); - else - m_leaf_end = m_leaf_start + static_cast(*m_leaf).size(); - REALM_ASSERT(m_leaf); - } - size_t end2 = (end > m_leaf_end ? m_leaf_end - m_leaf_start : end - m_leaf_start); - - if (m_leaf_type == StringColumn::leaf_type_Small) - s = static_cast(*m_leaf).find_first(m_value, s - m_leaf_start, end2); - else if (m_leaf_type == StringColumn::leaf_type_Medium) - s = static_cast(*m_leaf).find_first(m_value, s - m_leaf_start, end2); - else - s = static_cast(*m_leaf).find_first(str_to_bin(m_value), true, s - m_leaf_start, - end2); - - if (s == not_found) - s = m_leaf_end - 1; - else - return s + m_leaf_start; - } - - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new StringNode(*this, patches)); - } - - StringNode(const StringNode& from, QueryNodeHandoverPatches* patches) - : StringNodeBase(from, patches) - { - } - -private: - inline BinaryData str_to_bin(const StringData& s) noexcept - { - return BinaryData(s.data(), s.size()); - } - - size_t m_key_ndx = not_found; - size_t m_last_indexed; - - // Used for linear scan through enum-string - SequentialGetter m_cse; - - // Used for index lookup - std::unique_ptr m_index_matches; - bool m_index_matches_destroy = false; - std::unique_ptr> m_index_getter; - size_t m_results_start; - size_t m_results_end; - size_t m_last_start; -}; - -// OR node contains at least two node pointers: Two or more conditions to OR -// together in m_conditions, and the next AND condition (if any) in m_child. -// -// For 'second.equal(23).begin_group().first.equal(111).Or().first.equal(222).end_group().third().equal(555)', this -// will first set m_conditions[0] = left-hand-side through constructor, and then later, when .first.equal(222) is -// invoked, -// invocation will set m_conditions[1] = right-hand-side through Query& Query::Or() (see query.cpp). In there, m_child -// is -// also set to next AND condition (if any exists) following the OR. -class OrNode : public ParentNode { -public: - OrNode(std::unique_ptr condition) - { - m_dT = 50.0; - if (condition) - m_conditions.emplace_back(std::move(condition)); - } - - OrNode(const OrNode& other, QueryNodeHandoverPatches* patches) - : ParentNode(other, patches) - { - for (const auto& condition : other.m_conditions) { - m_conditions.emplace_back(condition->clone(patches)); - } - } - - void table_changed() override - { - for (auto& condition : m_conditions) { - condition->set_table(*m_table); - } - } - - void init() override - { - m_dD = 10.0; - - m_start.clear(); - m_start.resize(m_conditions.size(), 0); - - m_last.clear(); - m_last.resize(m_conditions.size(), 0); - - m_was_match.clear(); - m_was_match.resize(m_conditions.size(), false); - - std::vector v; - for (auto& condition : m_conditions) { - condition->init(); - v.clear(); - condition->gather_children(v); - } - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override - { - if (start >= end) - return not_found; - - size_t index = not_found; - - for (size_t c = 0; c < m_conditions.size(); ++c) { - // out of order search; have to discard cached results - if (start < m_start[c]) { - m_last[c] = 0; - m_was_match[c] = false; - } - // already searched this range and didn't match - else if (m_last[c] >= end) - continue; - // already search this range and *did* match - else if (m_was_match[c] && m_last[c] >= start) { - if (index > m_last[c]) - index = m_last[c]; - continue; - } - - m_start[c] = start; - size_t fmax = std::max(m_last[c], start); - size_t f = m_conditions[c]->find_first(fmax, end); - m_was_match[c] = f != not_found; - m_last[c] = f == not_found ? end : f; - if (f != not_found && index > m_last[c]) - index = m_last[c]; - } - - return index; - } - - std::string validate() override - { - if (error_code != "") - return error_code; - if (m_conditions.size() == 0) - return "Missing left-hand side of OR"; - if (m_conditions.size() == 1) - return "Missing right-hand side of OR"; - std::string s; - if (m_child != 0) - s = m_child->validate(); - if (s != "") - return s; - for (size_t i = 0; i < m_conditions.size(); ++i) { - s = m_conditions[i]->validate(); - if (s != "") - return s; - } - return ""; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new OrNode(*this, patches)); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - for (auto it = m_conditions.rbegin(); it != m_conditions.rend(); ++it) - (*it)->apply_handover_patch(patches, group); - - ParentNode::apply_handover_patch(patches, group); - } - - std::vector> m_conditions; - -private: - // start index of the last find for each cond - std::vector m_start; - // last looked at index of the lasft find for each cond - // is a matching index if m_was_match is true - std::vector m_last; - std::vector m_was_match; -}; - - -class NotNode : public ParentNode { -public: - NotNode(std::unique_ptr condition) - : m_condition(std::move(condition)) - { - m_dT = 50.0; - } - - void table_changed() override - { - m_condition->set_table(*m_table); - } - - void init() override - { - m_dD = 10.0; - - std::vector v; - - m_condition->init(); - v.clear(); - m_condition->gather_children(v); - - // Heuristics bookkeeping: - m_known_range_start = 0; - m_known_range_end = 0; - m_first_in_known_range = not_found; - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override; - - std::string validate() override - { - if (error_code != "") - return error_code; - if (m_condition == 0) - return "Missing argument to Not"; - std::string s; - if (m_child != 0) - s = m_child->validate(); - if (s != "") - return s; - s = m_condition->validate(); - if (s != "") - return s; - return ""; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new NotNode(*this, patches)); - } - - NotNode(const NotNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_condition(from.m_condition ? from.m_condition->clone(patches) : nullptr) - , m_known_range_start(from.m_known_range_start) - , m_known_range_end(from.m_known_range_end) - , m_first_in_known_range(from.m_first_in_known_range) - { - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_condition->apply_handover_patch(patches, group); - ParentNode::apply_handover_patch(patches, group); - } - - std::unique_ptr m_condition; - -private: - // FIXME This heuristic might as well be reused for all condition nodes. - size_t m_known_range_start; - size_t m_known_range_end; - size_t m_first_in_known_range; - - bool evaluate_at(size_t rowndx); - void update_known(size_t start, size_t end, size_t first); - size_t find_first_loop(size_t start, size_t end); - size_t find_first_covers_known(size_t start, size_t end); - size_t find_first_covered_by_known(size_t start, size_t end); - size_t find_first_overlap_lower(size_t start, size_t end); - size_t find_first_overlap_upper(size_t start, size_t end); - size_t find_first_no_overlap(size_t start, size_t end); -}; - - -// Compare two columns with eachother row-by-row -template -class TwoColumnsNode : public ParentNode { -public: - using TConditionValue = typename ColType::value_type; - - TwoColumnsNode(size_t column1, size_t column2) - { - m_dT = 100.0; - m_condition_column_idx1 = column1; - m_condition_column_idx2 = column2; - } - - ~TwoColumnsNode() noexcept override - { - delete[] m_value.data(); - } - - void table_changed() override - { - m_getter1.init(&get_column(m_condition_column_idx1)); - m_getter2.init(&get_column(m_condition_column_idx2)); - } - - void init() override - { - m_dD = 100.0; - - if (m_child) - m_child->init(); - } - - size_t find_first_local(size_t start, size_t end) override - { - size_t s = start; - - while (s < end) { - if (std::is_same::value) { - // For int64_t we've created an array intrinsics named compare_leafs which template expands bitwidths - // of boths arrays to make Get faster. - m_getter1.cache_next(s); - m_getter2.cache_next(s); - - QueryState qs; - bool resume = m_getter1.m_leaf_ptr->template compare_leafs( - m_getter2.m_leaf_ptr, s - m_getter1.m_leaf_start, m_getter1.local_end(end), 0, &qs, - CallbackDummy()); - - if (resume) - s = m_getter1.m_leaf_end; - else - return to_size_t(qs.m_state) + m_getter1.m_leaf_start; - } - else { -// This is for float and double. - -#if 0 && defined(REALM_COMPILER_AVX) -// AVX has been disabled because of array alignment (see https://app.asana.com/0/search/8836174089724/5763107052506) -// -// For AVX you can call things like if (sseavx<1>()) to test for AVX, and then utilize _mm256_movemask_ps (VC) -// or movemask_cmp_ps (gcc/clang) -// -// See https://github.com/rrrlasse/realm/tree/AVX for an example of utilizing AVX for a two-column search which has -// been benchmarked to: floats: 288 ms vs 552 by using AVX compared to 2-level-unrolled FPU loop. doubles: 415 ms vs -// 475 (more bandwidth bound). Tests against SSE have not been performed; AVX may not pay off. Please benchmark -#endif - - TConditionValue v1 = m_getter1.get_next(s); - TConditionValue v2 = m_getter2.get_next(s); - TConditionFunction C; - - if (C(v1, v2)) - return s; - else - s++; - } - } - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new TwoColumnsNode(*this, patches)); - } - - TwoColumnsNode(const TwoColumnsNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_value(from.m_value) - , m_condition_column(from.m_condition_column) - , m_column_type(from.m_column_type) - { - if (m_condition_column) - m_condition_column_idx = m_condition_column->get_column_index(); - copy_getter(m_getter1, m_condition_column_idx1, from.m_getter1, patches); - copy_getter(m_getter2, m_condition_column_idx2, from.m_getter2, patches); - } - -private: - BinaryData m_value; - const BinaryColumn* m_condition_column = nullptr; - ColumnType m_column_type; - - size_t m_condition_column_idx1 = not_found; - size_t m_condition_column_idx2 = not_found; - - SequentialGetter m_getter1; - SequentialGetter m_getter2; -}; - - -// For Next-Generation expressions like col1 / col2 + 123 > col4 * 100. -class ExpressionNode : public ParentNode { - -public: - ExpressionNode(std::unique_ptr expression) - : m_expression(std::move(expression)) - { - m_dD = 10.0; - m_dT = 50.0; - } - - void table_changed() override - { - m_expression->set_base_table(m_table.get()); - } - - size_t find_first_local(size_t start, size_t end) override - { - return m_expression->find_first(start, end); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new ExpressionNode(*this, patches)); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_expression->apply_handover_patch(patches, group); - ParentNode::apply_handover_patch(patches, group); - } - -private: - ExpressionNode(const ExpressionNode& from, QueryNodeHandoverPatches* patches) - : ParentNode(from, patches) - , m_expression(from.m_expression->clone(patches)) - { - } - - std::unique_ptr m_expression; -}; - - -struct LinksToNodeHandoverPatch : public QueryNodeHandoverPatch { - std::unique_ptr m_target_row; - size_t m_origin_column; -}; - -class LinksToNode : public ParentNode { -public: - LinksToNode(size_t origin_column_index, const ConstRow& target_row) - : m_origin_column(origin_column_index) - , m_target_row(target_row) - { - m_dD = 10.0; - m_dT = 50.0; - } - - void table_changed() override - { - m_column_type = m_table->get_column_type(m_origin_column); - m_column = &const_cast(m_table.get())->get_column_link_base(m_origin_column); - REALM_ASSERT(m_column_type == type_Link || m_column_type == type_LinkList); - } - - size_t find_first_local(size_t start, size_t end) override - { - REALM_ASSERT(m_column); - if (!m_target_row.is_attached()) - return not_found; - - if (m_column_type == type_Link) { - LinkColumn& cl = static_cast(*m_column); - return cl.find_first(m_target_row.get_index() + 1, start, - end); // LinkColumn stores link to row N as the integer N + 1 - } - else if (m_column_type == type_LinkList) { - LinkListColumn& cll = static_cast(*m_column); - - for (size_t i = start; i < end; i++) { - LinkViewRef lv = cll.get(i); - if (lv->find(m_target_row.get_index()) != not_found) - return i; - } - } - - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(patches ? new LinksToNode(*this, patches) : new LinksToNode(*this)); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - REALM_ASSERT(patches.size()); - std::unique_ptr abstract_patch = std::move(patches.back()); - patches.pop_back(); - - auto patch = dynamic_cast(abstract_patch.get()); - REALM_ASSERT(patch); - - m_origin_column = patch->m_origin_column; - m_target_row.apply_and_consume_patch(patch->m_target_row, group); - - ParentNode::apply_handover_patch(patches, group); - } - -private: - size_t m_origin_column = npos; - ConstRow m_target_row; - LinkColumnBase* m_column = nullptr; - DataType m_column_type; - - LinksToNode(const LinksToNode& source, QueryNodeHandoverPatches* patches) - : ParentNode(source, patches) - { - auto patch = std::make_unique(); - patch->m_origin_column = source.m_column->get_column_index(); - ConstRow::generate_patch(source.m_target_row, patch->m_target_row); - patches->push_back(std::move(patch)); - } -}; - -} // namespace realm - -#endif // REALM_QUERY_ENGINE_HPP diff --git a/Example/Pods/Realm/include/core/realm/query_expression.hpp b/Example/Pods/Realm/include/core/realm/query_expression.hpp deleted file mode 100644 index 2d7b0a6..0000000 --- a/Example/Pods/Realm/include/core/realm/query_expression.hpp +++ /dev/null @@ -1,3109 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -/* -This file lets you write queries in C++ syntax like: Expression* e = (first + 1 / second >= third + 12.3); - -Type conversion/promotion semantics is the same as in the C++ expressions, e.g float + int > double == float + -(float)int > double. - - -Grammar: ------------------------------------------------------------------------------------------------------------------------ - Expression: Subexpr2 Compare Subexpr2 - operator! Expression - - Subexpr2: Value - Columns - Subexpr2 Operator Subexpr2 - power(Subexpr2) // power(x) = x * x, as example of unary operator - - Value: T - - Operator>: +, -, *, / - - Compare: ==, !=, >=, <=, >, < - - T: bool, int, int64_t, float, double, StringData - - -Class diagram ------------------------------------------------------------------------------------------------------------------------ -Subexpr2 - void evaluate(size_t i, ValueBase* destination) - -Compare: public Subexpr2 - size_t find_first(size_t start, size_t end) // main method that executes query - - unique_ptr m_left; // left expression subtree - unique_ptr m_right; // right expression subtree - -Operator: public Subexpr2 - void evaluate(size_t i, ValueBase* destination) - unique_ptr m_left; // left expression subtree - unique_ptr m_right; // right expression subtree - -Value: public Subexpr2 - void evaluate(size_t i, ValueBase* destination) - T m_v[8]; - -Columns: public Subexpr2 - void evaluate(size_t i, ValueBase* destination) - SequentialGetter sg; // class bound to a column, lets you read values in a fast way - Table* m_table; - -class ColumnAccessor<>: public Columns - - -Call diagram: ------------------------------------------------------------------------------------------------------------------------ -Example of 'table.first > 34.6 + table.second': - -size_t Compare::find_first()-------------+ - | | - | | - | | - +--> Columns::evaluate() +--------> Operator::evaluate() - | | - Value::evaluate() Columns::evaluate() - -Operator, Value and Columns have an evaluate(size_t i, ValueBase* destination) method which returns a Value -containing 8 values representing table rows i...i + 7. - -So Value contains 8 concecutive values and all operations are based on these chunks. This is -to save overhead by virtual calls needed for evaluating a query that has been dynamically constructed at runtime. - - -Memory allocation: ------------------------------------------------------------------------------------------------------------------------ -Subexpressions created by the end-user are stack allocated. They are cloned to the heap when passed to UnaryOperator, -Operator, and Compare. Those types own the clones and deallocate them when destroyed. - - -Caveats, notes and todos ------------------------------------------------------------------------------------------------------------------------ - * Perhaps disallow columns from two different tables in same expression - * The name Columns (with s) an be confusing because we also have Column (without s) - * We have Columns::m_table, Query::m_table and ColumnAccessorBase::m_table that point at the same thing, even with - ColumnAccessor<> extending Columns. So m_table is redundant, but this is in order to keep class dependencies and - entanglement low so that the design is flexible (if you perhaps later want a Columns class that is not dependent - on ColumnAccessor) - -Nulls ------------------------------------------------------------------------------------------------------------------------ -First note that at array level, nulls are distinguished between non-null in different ways: -String: - m_data == 0 && m_size == 0 - -Integer, Bool, OldDateTime stored in ArrayIntNull: - value == get(0) (entry 0 determins a magic value that represents nulls) - -Float/double: - null::is_null(value) which tests if value bit-matches one specific bit pattern reserved for null - -The Columns class encapsulates all this into a simple class that, for any type T has - evaluate(size_t index) that reads values from a column, taking nulls in count - get(index) - set(index) - is_null(index) - set_null(index) -*/ - -#ifndef REALM_QUERY_EXPRESSION_HPP -#define REALM_QUERY_EXPRESSION_HPP - -#include -#include -#include - -#include - -// Normally, if a next-generation-syntax condition is supported by the old query_engine.hpp, a query_engine node is -// created because it's faster (by a factor of 5 - 10). Because many of our existing next-generation-syntax unit -// unit tests are indeed simple enough to fallback to old query_engine, query_expression gets low test coverage. Undef -// flag to get higher query_expression test coverage. This is a good idea to try out each time you develop on/modify -// query_expression. - -#define REALM_OLDQUERY_FALLBACK - -namespace realm { - -template -T minimum(T a, T b) -{ - return a < b ? a : b; -} - -// FIXME, this needs to exist elsewhere -typedef int64_t Int; -typedef bool Bool; -typedef realm::OldDateTime OldDateTime; -typedef float Float; -typedef double Double; -typedef realm::StringData String; -typedef realm::BinaryData Binary; - -#ifdef REALM_OLDQUERY_FALLBACK -// Hack to avoid template instantiation errors. See create(). Todo, see if we can simplify only_numeric somehow -namespace { -template -T only_numeric(U in) -{ - return static_cast(util::unwrap(in)); -} - -template -int only_numeric(const StringData&) -{ - REALM_ASSERT(false); - return 0; -} - -template -int only_numeric(const BinaryData&) -{ - REALM_ASSERT(false); - return 0; -} - -template -StringData only_string(T in) -{ - REALM_ASSERT(false); - static_cast(in); - return StringData(); -} - -StringData only_string(StringData in) -{ - return in; -} - -template -T no_timestamp(U in) -{ - return static_cast(util::unwrap(in)); -} - -template -int no_timestamp(const Timestamp&) -{ - REALM_ASSERT(false); - return 0; -} -#endif // REALM_OLDQUERY_FALLBACK - -} // anonymous namespace - -template -struct Plus { - T operator()(T v1, T v2) const - { - return v1 + v2; - } - typedef T type; -}; - -template -struct Minus { - T operator()(T v1, T v2) const - { - return v1 - v2; - } - typedef T type; -}; - -template -struct Div { - T operator()(T v1, T v2) const - { - return v1 / v2; - } - typedef T type; -}; - -template -struct Mul { - T operator()(T v1, T v2) const - { - return v1 * v2; - } - typedef T type; -}; - -// Unary operator -template -struct Pow { - T operator()(T v) const - { - return v * v; - } - typedef T type; -}; - -// Finds a common type for T1 and T2 according to C++ conversion/promotion in arithmetic (float + int => float, etc) -template ::is_integer || std::is_same::value, - bool T2_is_int = std::numeric_limits::is_integer || std::is_same::value, - bool T1_is_widest = (sizeof(T1) > sizeof(T2) || std::is_same::value)> -struct Common; -template -struct Common { - typedef T1 type; -}; -template -struct Common { - typedef T2 type; -}; -template -struct Common { - typedef T1 type; -}; -template -struct Common { - typedef T2 type; -}; - - -struct RowIndex { - enum DetachedTag { - Detached, - }; - - explicit RowIndex() - : m_row_index(npos) - { - } - explicit RowIndex(size_t row_index) - : m_row_index(row_index) - { - } - RowIndex(DetachedTag) - : m_row_index() - { - } - - bool is_attached() const - { - return bool(m_row_index); - } - bool is_null() const - { - return is_attached() && *m_row_index == npos; - } - - bool operator==(const RowIndex& other) const - { - // Row indexes that are detached are never equal to any other row index. - if (!is_attached() || !other.is_attached()) - return false; - return m_row_index == other.m_row_index; - } - bool operator!=(const RowIndex& other) const - { - return !(*this == other); - } - -private: - util::Optional m_row_index; -}; - - -struct ValueBase { - static const size_t default_size = 8; - virtual void export_bool(ValueBase& destination) const = 0; - virtual void export_Timestamp(ValueBase& destination) const = 0; - virtual void export_int(ValueBase& destination) const = 0; - virtual void export_float(ValueBase& destination) const = 0; - virtual void export_int64_t(ValueBase& destination) const = 0; - virtual void export_double(ValueBase& destination) const = 0; - virtual void export_StringData(ValueBase& destination) const = 0; - virtual void export_BinaryData(ValueBase& destination) const = 0; - virtual void export_RowIndex(ValueBase& destination) const = 0; - virtual void export_null(ValueBase& destination) const = 0; - virtual void import(const ValueBase& destination) = 0; - - // If true, all values in the class come from a link list of a single field in the parent table (m_table). If - // false, then values come from successive rows of m_table (query operations are operated on in bulks for speed) - bool m_from_link_list; - - // Number of values stored in the class. - size_t m_values; -}; - -class Expression { -public: - Expression() - { - } - virtual ~Expression() - { - } - - virtual size_t find_first(size_t start, size_t end) const = 0; - virtual void set_base_table(const Table* table) = 0; - virtual const Table* get_base_table() const = 0; - - virtual std::unique_ptr clone(QueryNodeHandoverPatches*) const = 0; - virtual void apply_handover_patch(QueryNodeHandoverPatches&, Group&) - { - } -}; - -template -std::unique_ptr make_expression(Args&&... args) -{ - return std::unique_ptr(new T(std::forward(args)...)); -} - -class Subexpr { -public: - virtual ~Subexpr() - { - } - - virtual std::unique_ptr clone(QueryNodeHandoverPatches* = nullptr) const = 0; - virtual void apply_handover_patch(QueryNodeHandoverPatches&, Group&) - { - } - - // When the user constructs a query, it always "belongs" to one single base/parent table (regardless of - // any links or not and regardless of any queries assembled with || or &&). When you do a Query::find(), - // then Query::m_table is set to this table, and set_base_table() is called on all Columns and LinkMaps in - // the query expression tree so that they can set/update their internals as required. - // - // During thread-handover of a Query, set_base_table() is also called to make objects point at the new table - // instead of the old one from the old thread. - virtual void set_base_table(const Table*) - { - } - - // Recursively fetch tables of columns in expression tree. Used when user first builds a stand-alone expression - // and - // binds it to a Query at a later time - virtual const Table* get_base_table() const - { - return nullptr; - } - - virtual void evaluate(size_t index, ValueBase& destination) = 0; -}; - -template -std::unique_ptr make_subexpr(Args&&... args) -{ - return std::unique_ptr(new T(std::forward(args)...)); -} - -template -class Columns; -template -class Value; -class ConstantStringValue; -template -class Subexpr2; -template -class Operator; -template -class UnaryOperator; -template -class Compare; -template -class UnaryLinkCompare; -class ColumnAccessorBase; - - -// Handle cases where left side is a constant (int, float, int64_t, double, StringData) -template -Query create(L left, const Subexpr2& right) -{ -// Purpose of below code is to intercept the creation of a condition and test if it's supported by the old -// query_engine.hpp which is faster. If it's supported, create a query_engine.hpp node, otherwise create a -// query_expression.hpp node. -// -// This method intercepts only Value Subexpr2. Interception of Subexpr2 Subexpr is elsewhere. - -#ifdef REALM_OLDQUERY_FALLBACK // if not defined, then never fallback to query_engine.hpp; always use query_expression - const Columns* column = dynamic_cast*>(&right); - - if (column && ((std::numeric_limits::is_integer && std::numeric_limits::is_integer) || - (std::is_same::value && std::is_same::value) || - (std::is_same::value && std::is_same::value) || - (std::is_same::value && std::is_same::value) || - (std::is_same::value && std::is_same::value) || - (std::is_same::value && std::is_same::value)) && - !column->links_exist()) { - const Table* t = column->get_base_table(); - Query q = Query(*t); - - if (std::is_same::value) - q.greater(column->column_ndx(), only_numeric(left)); - else if (std::is_same::value) - q.less(column->column_ndx(), only_numeric(left)); - else if (std::is_same::value) - q.equal(column->column_ndx(), left); - else if (std::is_same::value) - q.not_equal(column->column_ndx(), left); - else if (std::is_same::value) - q.greater_equal(column->column_ndx(), only_numeric(left)); - else if (std::is_same::value) - q.less_equal(column->column_ndx(), only_numeric(left)); - else if (std::is_same::value) - q.equal(column->column_ndx(), only_string(left), false); - else if (std::is_same::value) - q.not_equal(column->column_ndx(), only_string(left), false); - else if (std::is_same::value) - q.begins_with(column->column_ndx(), only_string(left)); - else if (std::is_same::value) - q.begins_with(column->column_ndx(), only_string(left), false); - else if (std::is_same::value) - q.ends_with(column->column_ndx(), only_string(left)); - else if (std::is_same::value) - q.ends_with(column->column_ndx(), only_string(left), false); - else if (std::is_same::value) - q.contains(column->column_ndx(), only_string(left)); - else if (std::is_same::value) - q.contains(column->column_ndx(), only_string(left), false); - else if (std::is_same::value) - q.like(column->column_ndx(), only_string(left)); - else if (std::is_same::value) - q.like(column->column_ndx(), only_string(left), false); - else { - // query_engine.hpp does not support this Cond. Please either add support for it in query_engine.hpp or - // fallback to using use 'return new Compare<>' instead. - REALM_ASSERT(false); - } - // Return query_engine.hpp node - return q; - } - else -#endif - { - // Return query_expression.hpp node - using CommonType = typename Common::type; - using ValueType = - typename std::conditional::value, ConstantStringValue, Value>::type; - return make_expression>(make_subexpr(left), right.clone()); - } -} - - -// All overloads where left-hand-side is Subexpr2: -// -// left-hand-side operator right-hand-side -// Subexpr2 +, -, *, /, <, >, ==, !=, <=, >= R, Subexpr2 -// -// For L = R = {int, int64_t, float, double, StringData, Timestamp}: -template -class Overloads { - typedef typename Common::type CommonType; - - std::unique_ptr clone_subexpr() const - { - return static_cast&>(*this).clone(); - } - -public: - // Arithmetic, right side constant - Operator> operator+(R right) const - { - return {clone_subexpr(), make_subexpr>(right)}; - } - Operator> operator-(R right) const - { - return {clone_subexpr(), make_subexpr>(right)}; - } - Operator> operator*(R right) const - { - return {clone_subexpr(), make_subexpr>(right)}; - } - Operator> operator/(R right) const - { - return {clone_subexpr(), make_subexpr>(right)}; - } - - // Arithmetic, right side subexpression - Operator> operator+(const Subexpr2& right) const - { - return {clone_subexpr(), right.clone()}; - } - Operator> operator-(const Subexpr2& right) const - { - return {clone_subexpr(), right.clone()}; - } - Operator> operator*(const Subexpr2& right) const - { - return {clone_subexpr(), right.clone()}; - } - Operator> operator/(const Subexpr2& right) const - { - return {clone_subexpr(), right.clone()}; - } - - // Compare, right side constant - Query operator>(R right) - { - return create(right, static_cast&>(*this)); - } - Query operator<(R right) - { - return create(right, static_cast&>(*this)); - } - Query operator>=(R right) - { - return create(right, static_cast&>(*this)); - } - Query operator<=(R right) - { - return create(right, static_cast&>(*this)); - } - Query operator==(R right) - { - return create(right, static_cast&>(*this)); - } - Query operator!=(R right) - { - return create(right, static_cast&>(*this)); - } - - // Purpose of this method is to intercept the creation of a condition and test if it's supported by the old - // query_engine.hpp which is faster. If it's supported, create a query_engine.hpp node, otherwise create a - // query_expression.hpp node. - // - // This method intercepts Subexpr2 Subexpr2 only. Value Subexpr2 is intercepted elsewhere. - template - Query create2(const Subexpr2& right) - { -#ifdef REALM_OLDQUERY_FALLBACK // if not defined, never fallback query_engine; always use query_expression - // Test if expressions are of type Columns. Other possibilities are Value and Operator. - const Columns* left_col = dynamic_cast*>(static_cast*>(this)); - const Columns* right_col = dynamic_cast*>(&right); - - // query_engine supports 'T-column ' for T = {int64_t, float, double}, op = {<, >, ==, !=, <=, - // >=}, - // but only if both columns are non-nullable, and aren't in linked tables. - if (left_col && right_col && std::is_same::value && !left_col->is_nullable() && - !right_col->is_nullable() && !left_col->links_exist() && !right_col->links_exist() && - !std::is_same::value) { - const Table* t = left_col->get_base_table(); - Query q = Query(*t); - - if (std::numeric_limits::is_integer || std::is_same::value) { - if (std::is_same::value) - q.less_int(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_int(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.equal_int(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.not_equal_int(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.less_equal_int(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_equal_int(left_col->column_ndx(), right_col->column_ndx()); - else { - REALM_ASSERT(false); - } - } - else if (std::is_same::value) { - if (std::is_same::value) - q.less_float(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_float(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.equal_float(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.not_equal_float(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.less_equal_float(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_equal_float(left_col->column_ndx(), right_col->column_ndx()); - else { - REALM_ASSERT(false); - } - } - else if (std::is_same::value) { - if (std::is_same::value) - q.less_double(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_double(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.equal_double(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.not_equal_double(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.less_equal_double(left_col->column_ndx(), right_col->column_ndx()); - else if (std::is_same::value) - q.greater_equal_double(left_col->column_ndx(), right_col->column_ndx()); - else { - REALM_ASSERT(false); - } - } - else { - REALM_ASSERT(false); - } - // Return query_engine.hpp node - return q; - } - else -#endif - { - // Return query_expression.hpp node - return make_expression::type>>(clone_subexpr(), right.clone()); - } - } - - // Compare, right side subexpression - Query operator==(const Subexpr2& right) - { - return create2(right); - } - Query operator!=(const Subexpr2& right) - { - return create2(right); - } - Query operator>(const Subexpr2& right) - { - return create2(right); - } - Query operator<(const Subexpr2& right) - { - return create2(right); - } - Query operator>=(const Subexpr2& right) - { - return create2(right); - } - Query operator<=(const Subexpr2& right) - { - return create2(right); - } -}; - -// With this wrapper class we can define just 20 overloads inside Overloads instead of 5 * 20 = 100. Todo: We -// can -// consider if it's simpler/better to remove this class completely and just list all 100 overloads manually anyway. -template -class Subexpr2 : public Subexpr, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads, - public Overloads { -public: - virtual ~Subexpr2() - { - } - -#define RLM_U2(t, o) using Overloads::operator o; -#define RLM_U(o) \ - RLM_U2(int, o) \ - RLM_U2(float, o) \ - RLM_U2(double, o) \ - RLM_U2(int64_t, o) \ - RLM_U2(StringData, o) RLM_U2(bool, o) RLM_U2(OldDateTime, o) RLM_U2(Timestamp, o) RLM_U2(null, o) - RLM_U(+) RLM_U(-) RLM_U(*) RLM_U(/) RLM_U(>) RLM_U(<) RLM_U(==) RLM_U(!=) RLM_U(>=) RLM_U(<=) -}; - -// Subexpr2 only provides equality comparisons. Their implementations can be found later in this file. -template <> -class Subexpr2 : public Subexpr { -}; - - -/* -This class is used to store N values of type T = {int64_t, bool, OldDateTime or StringData}, and allows an entry -to be null too. It's used by the Value class for internal storage. - -To indicate nulls, we could have chosen a separate bool vector or some other bitmask construction. But for -performance, we customize indication of nulls to match the same indication that is used in the persisted database -file - -Queries in query_expression.hpp execute by processing chunks of 8 rows at a time. Assume you have a column: - - price (int) = {1, 2, 3, null, 1, 6, 6, 9, 5, 2, null} - -And perform a query: - - Query q = (price + 2 == 5); - -query_expression.hpp will then create a NullableVector = {5, 5, 5, 5, 5, 5, 5, 5} and then read values -NullableVector = {1, 2, 3, null, 1, 6, 6, 9} from the column, and then perform `+` and `==` on these chunks. - -See the top of this file for more information on all this. - -Assume the user specifies the null constant in a query: - -Query q = (price == null) - -The query system will then construct a NullableVector of type `null` (NullableVector). This allows compile -time optimizations for these cases. -*/ - -template -struct NullableVector { - using Underlying = typename util::RemoveOptional::type; - using t_storage = - typename std::conditional::value || std::is_same::value, - int64_t, Underlying>::type; - - NullableVector() - { - } - - NullableVector& operator=(const NullableVector& other) - { - if (this != &other) { - init(other.m_size); - std::copy(other.m_first, other.m_first + other.m_size, m_first); - m_null = other.m_null; - } - return *this; - } - - NullableVector(const NullableVector& other) - { - init(other.m_size); - std::copy(other.m_first, other.m_first + other.m_size, m_first); - m_null = other.m_null; - } - - ~NullableVector() - { - dealloc(); - } - - T operator[](size_t index) const - { - REALM_ASSERT_3(index, <, m_size); - return static_cast(m_first[index]); - } - - inline bool is_null(size_t index) const - { - REALM_ASSERT((std::is_same::value)); - return m_first[index] == m_null; - } - - inline void set_null(size_t index) - { - REALM_ASSERT((std::is_same::value)); - m_first[index] = m_null; - } - - template - typename std::enable_if::value, void>::type set(size_t index, t_storage value) - { - REALM_ASSERT((std::is_same::value)); - - // If value collides with magic null value, then switch to a new unique representation for null - if (REALM_UNLIKELY(value == m_null)) { - // adding a prime will generate 2^64 unique values. Todo: Only works on 2's complement architecture - uint64_t candidate = static_cast(m_null) + 0xfffffffbULL; - while (std::find(m_first, m_first + m_size, static_cast(candidate)) != m_first + m_size) - candidate += 0xfffffffbULL; - std::replace(m_first, m_first + m_size, m_null, static_cast(candidate)); - } - m_first[index] = value; - } - - template - typename std::enable_if< - realm::is_any::value, - void>::type - set(size_t index, t_storage value) - { - m_first[index] = value; - } - - - inline util::Optional get(size_t index) const - { - if (is_null(index)) - return util::none; - - return util::make_optional((*this)[index]); - } - - inline void set(size_t index, util::Optional value) - { - if (value) { - Underlying v = *value; - set(index, v); - } - else { - set_null(index); - } - } - - void fill(T value) - { - for (size_t t = 0; t < m_size; t++) { - if (std::is_same::value) - set_null(t); - else - set(t, value); - } - } - - void init(size_t size) - { - if (size == m_size) - return; - - dealloc(); - m_size = size; - if (m_size > 0) { - if (m_size > prealloc) - m_first = reinterpret_cast(new t_storage[m_size]); - else - m_first = m_cache; - } - } - - void init(size_t size, T values) - { - init(size); - fill(values); - } - - void dealloc() - { - if (m_first) { - if (m_size > prealloc) - delete[] m_first; - m_first = nullptr; - } - } - - t_storage m_cache[prealloc]; - t_storage* m_first = &m_cache[0]; - size_t m_size = 0; - - int64_t m_null = reinterpret_cast(&m_null); // choose magic value to represent nulls -}; - -// Double -// NOTE: fails in gcc 4.8 without `inline`. Do not remove. Same applies for all methods below. -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return null::is_null_float(m_first[index]); -} - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = null::get_null_float(); -} - -// Float -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return null::is_null_float(m_first[index]); -} - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = null::get_null_float(); -} - - -// Null -template <> -inline void NullableVector::set_null(size_t) -{ - return; -} -template <> -inline bool NullableVector::is_null(size_t) const -{ - return true; -} - - -// OldDateTime -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return m_first[index].get_olddatetime() == m_null; -} - - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = m_null; -} - -// StringData - -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return m_first[index].is_null(); -} - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = StringData(); -} - -// BinaryData - -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return m_first[index].is_null(); -} - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = BinaryData(); -} - -// RowIndex -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return m_first[index].is_null(); -} -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = RowIndex(); -} - - -// Timestamp - -template <> -inline bool NullableVector::is_null(size_t index) const -{ - return m_first[index].is_null(); -} - -template <> -inline void NullableVector::set_null(size_t index) -{ - m_first[index] = Timestamp{}; -} - - -template -struct OperatorOptionalAdapter { - template - util::Optional operator()(const util::Optional& left, const util::Optional& right) - { - if (!left || !right) - return util::none; - return Operator()(*left, *right); - } - - template - util::Optional operator()(const util::Optional& arg) - { - if (!arg) - return util::none; - return Operator()(*arg); - } -}; - -// Stores N values of type T. Can also exchange data with other ValueBase of different types -template -class Value : public ValueBase, public Subexpr2 { -public: - Value() - { - init(false, ValueBase::default_size, T()); - } - Value(T v) - { - init(false, ValueBase::default_size, v); - } - - Value(bool from_link_list, size_t values) - { - init(from_link_list, values, T()); - } - - Value(bool from_link_list, size_t values, T v) - { - init(from_link_list, values, v); - } - - Value(const Value&) = default; - Value& operator=(const Value&) = default; - - void init(bool from_link_list, size_t values, T v) - { - m_storage.init(values, v); - ValueBase::m_from_link_list = from_link_list; - ValueBase::m_values = values; - } - - void init(bool from_link_list, size_t values) - { - m_storage.init(values); - ValueBase::m_from_link_list = from_link_list; - ValueBase::m_values = values; - } - - void evaluate(size_t, ValueBase& destination) override - { - destination.import(*this); - } - - - template - REALM_FORCEINLINE void fun(const Value* left, const Value* right) - { - OperatorOptionalAdapter o; - - if (!left->m_from_link_list && !right->m_from_link_list) { - // Operate on values one-by-one (one value is one row; no links) - size_t min = std::min(left->m_values, right->m_values); - init(false, min); - - for (size_t i = 0; i < min; i++) { - m_storage.set(i, o(left->m_storage.get(i), right->m_storage.get(i))); - } - } - else if (left->m_from_link_list && right->m_from_link_list) { - // FIXME: Many-to-many links not supported yet. Need to specify behaviour - REALM_ASSERT_DEBUG(false); - } - else if (!left->m_from_link_list && right->m_from_link_list) { - // Right values come from link. Left must come from single row. - REALM_ASSERT_DEBUG(left->m_values > 0); - init(true, right->m_values); - - auto left_value = left->m_storage.get(0); - for (size_t i = 0; i < right->m_values; i++) { - m_storage.set(i, o(left_value, right->m_storage.get(i))); - } - } - else if (left->m_from_link_list && !right->m_from_link_list) { - // Same as above, but with left values coming from links - REALM_ASSERT_DEBUG(right->m_values > 0); - init(true, left->m_values); - - auto right_value = right->m_storage.get(0); - for (size_t i = 0; i < left->m_values; i++) { - m_storage.set(i, o(left->m_storage.get(i), right_value)); - } - } - } - - template - REALM_FORCEINLINE void fun(const Value* value) - { - init(value->m_from_link_list, value->m_values); - - OperatorOptionalAdapter o; - for (size_t i = 0; i < value->m_values; i++) { - m_storage.set(i, o(value->m_storage.get(i))); - } - } - - - // Below import and export methods are for type conversion between float, double, int64_t, etc. - template - typename std::enable_if::value>::type REALM_FORCEINLINE - export2(ValueBase& destination) const - { - Value& d = static_cast&>(destination); - d.init(ValueBase::m_from_link_list, ValueBase::m_values, D()); - for (size_t t = 0; t < ValueBase::m_values; t++) { - if (m_storage.is_null(t)) - d.m_storage.set_null(t); - else { - d.m_storage.set(t, static_cast(m_storage[t])); - } - } - } - - template - typename std::enable_if::value>::type REALM_FORCEINLINE export2(ValueBase&) const - { - // export2 is instantiated for impossible conversions like T=StringData, D=int64_t. These are never - // performed at runtime but would result in a compiler error if we did not provide this implementation. - REALM_ASSERT_DEBUG(false); - } - - REALM_FORCEINLINE void export_Timestamp(ValueBase& destination) const override - { - export2(destination); - } - - REALM_FORCEINLINE void export_bool(ValueBase& destination) const override - { - export2(destination); - } - - REALM_FORCEINLINE void export_int64_t(ValueBase& destination) const override - { - export2(destination); - } - - REALM_FORCEINLINE void export_float(ValueBase& destination) const override - { - export2(destination); - } - - REALM_FORCEINLINE void export_int(ValueBase& destination) const override - { - export2(destination); - } - - REALM_FORCEINLINE void export_double(ValueBase& destination) const override - { - export2(destination); - } - REALM_FORCEINLINE void export_StringData(ValueBase& destination) const override - { - export2(destination); - } - REALM_FORCEINLINE void export_BinaryData(ValueBase& destination) const override - { - export2(destination); - } - REALM_FORCEINLINE void export_RowIndex(ValueBase& destination) const override - { - export2(destination); - } - REALM_FORCEINLINE void export_null(ValueBase& destination) const override - { - Value& d = static_cast&>(destination); - d.init(m_from_link_list, m_values); - } - - REALM_FORCEINLINE void import(const ValueBase& source) override - { - if (std::is_same::value) - source.export_int(*this); - else if (std::is_same::value) - source.export_Timestamp(*this); - else if (std::is_same::value) - source.export_bool(*this); - else if (std::is_same::value) - source.export_float(*this); - else if (std::is_same::value) - source.export_double(*this); - else if (std::is_same::value || std::is_same::value || - std::is_same::value) - source.export_int64_t(*this); - else if (std::is_same::value) - source.export_StringData(*this); - else if (std::is_same::value) - source.export_BinaryData(*this); - else if (std::is_same::value) - source.export_RowIndex(*this); - else if (std::is_same::value) - source.export_null(*this); - else - REALM_ASSERT_DEBUG(false); - } - - // Given a TCond (==, !=, >, <, >=, <=) and two Value, return index of first match - template - REALM_FORCEINLINE static size_t compare(Value* left, Value* right) - { - TCond c; - - if (!left->m_from_link_list && !right->m_from_link_list) { - // Compare values one-by-one (one value is one row; no link lists) - size_t min = minimum(left->ValueBase::m_values, right->ValueBase::m_values); - for (size_t m = 0; m < min; m++) { - - if (c(left->m_storage[m], right->m_storage[m], left->m_storage.is_null(m), - right->m_storage.is_null(m))) - return m; - } - } - else if (left->m_from_link_list && right->m_from_link_list) { - // FIXME: Many-to-many links not supported yet. Need to specify behaviour - REALM_ASSERT_DEBUG(false); - } - else if (!left->m_from_link_list && right->m_from_link_list) { - // Right values come from link list. Left must come from single row. Semantics: Match if at least 1 - // linked-to-value fulfills the condition - REALM_ASSERT_DEBUG(left->m_values > 0); - for (size_t r = 0; r < right->m_values; r++) { - if (c(left->m_storage[0], right->m_storage[r], left->m_storage.is_null(0), - right->m_storage.is_null(r))) - return 0; - } - } - else if (left->m_from_link_list && !right->m_from_link_list) { - // Same as above, but with left values coming from link list. - REALM_ASSERT_DEBUG(right->m_values > 0); - for (size_t l = 0; l < left->m_values; l++) { - if (c(left->m_storage[l], right->m_storage[0], left->m_storage.is_null(l), - right->m_storage.is_null(0))) - return 0; - } - } - - return not_found; // no match - } - - std::unique_ptr clone(QueryNodeHandoverPatches*) const override - { - return make_subexpr>(*this); - } - - NullableVector m_storage; -}; - -class ConstantStringValue : public Value { -public: - ConstantStringValue(const StringData& string) - : Value() - , m_string(string.is_null() ? util::none : util::make_optional(std::string(string))) - { - init(false, ValueBase::default_size, m_string); - } - - std::unique_ptr clone(QueryNodeHandoverPatches*) const override - { - return std::unique_ptr(new ConstantStringValue(*this)); - } - -private: - ConstantStringValue(const ConstantStringValue& other) - : Value() - , m_string(other.m_string) - { - init(other.m_from_link_list, other.m_values, m_string); - } - - util::Optional m_string; -}; - -// All overloads where left-hand-side is L: -// -// left-hand-side operator right-hand-side -// L +, -, *, /, <, >, ==, !=, <=, >= Subexpr2 -// -// For L = R = {int, int64_t, float, double, Timestamp}: -// Compare numeric values -template -Query operator>(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} - -template -Query operator<(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator==(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator==(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator==(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator==(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator==(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>=(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>=(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>=(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>=(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator>=(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<=(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<=(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<=(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<=(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator<=(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator!=(double left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator!=(float left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator!=(int left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator!=(int64_t left, const Subexpr2& right) -{ - return create(left, right); -} -template -Query operator!=(Timestamp left, const Subexpr2& right) -{ - return create(left, right); -} - -// Arithmetic -template -Operator::type>> operator+(double left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator+(float left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator+(int left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator+(int64_t left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator-(double left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator-(float left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator-(int left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator-(int64_t left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator*(double left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator*(float left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator*(int left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator*(int64_t left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator/(double left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator/(float left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator/(int left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} -template -Operator::type>> operator/(int64_t left, const Subexpr2& right) -{ - return {make_subexpr>(left), right.clone()}; -} - -// Unary operators -template -UnaryOperator> power(const Subexpr2& left) -{ - return {left.clone()}; -} - - -// Classes used for LinkMap (see below). -struct LinkMapFunction { - // Your consume() method is given row index of the linked-to table as argument, and you must return whether or - // not you want the LinkMapFunction to exit (return false) or continue (return true) harvesting the link tree - // for the current main table row index (it will be a link tree if you have multiple type_LinkList columns - // in a link()->link() query. - virtual bool consume(size_t row_index) = 0; -}; - -struct FindNullLinks : public LinkMapFunction { - bool consume(size_t row_index) override - { - static_cast(row_index); - m_has_link = true; - return false; // we've found a row index, so this can't be a null-link, so exit link harvesting - } - - bool m_has_link = false; -}; - -struct MakeLinkVector : public LinkMapFunction { - MakeLinkVector(std::vector& result) - : m_links(result) - { - } - - bool consume(size_t row_index) override - { - m_links.push_back(row_index); - return true; // continue evaluation - } - std::vector& m_links; -}; - -struct CountLinks : public LinkMapFunction { - bool consume(size_t) override - { - m_link_count++; - return true; - } - - size_t result() const - { - return m_link_count; - } - - size_t m_link_count = 0; -}; - - -/* -The LinkMap and LinkMapFunction classes are used for query conditions on links themselves (contrary to conditions on -the value payload they point at). - -MapLink::map_links() takes a row index of the link column as argument and follows any link chain stated in the query -(through the link()->link() methods) until the final payload table is reached, and then applies LinkMapFunction on -the linked-to row index(es). - -If all link columns are type_Link, then LinkMapFunction is only invoked for a single row index. If one or more -columns are type_LinkList, then it may result in multiple row indexes. - -The reason we use this map pattern is that we can exit the link-tree-traversal as early as possible, e.g. when we've -found the first link that points to row '5'. Other solutions could be a std::vector harvest_all_links(), or an -iterator pattern. First solution can't exit, second solution requires internal state. -*/ -class LinkMap { -public: - LinkMap() = default; - LinkMap(const Table* table, std::vector columns) - : m_link_column_indexes(std::move(columns)) - { - set_base_table(table); - } - - LinkMap(LinkMap const& other, QueryNodeHandoverPatches* patches) - : LinkMap(other) - { - if (!patches) - return; - - m_link_column_indexes.clear(); - const Table* table = m_base_table; - m_base_table = nullptr; - for (auto column : m_link_columns) { - m_link_column_indexes.push_back(column->get_column_index()); - if (table->get_real_column_type(m_link_column_indexes.back()) == col_type_BackLink) - table = &static_cast(column)->get_origin_table(); - else - table = &static_cast(column)->get_target_table(); - } - } - - void set_base_table(const Table* table) - { - if (table == m_base_table) - return; - - m_base_table = table; - m_link_columns.clear(); - m_link_types.clear(); - m_only_unary_links = true; - - for (size_t link_column_index : m_link_column_indexes) { - // Link column can be either LinkList or single Link - ColumnType type = table->get_real_column_type(link_column_index); - REALM_ASSERT(Table::is_link_type(type) || type == col_type_BackLink); - m_link_types.push_back(type); - - if (type == col_type_LinkList) { - const LinkListColumn& cll = table->get_column_link_list(link_column_index); - m_link_columns.push_back(&cll); - m_only_unary_links = false; - table = &cll.get_target_table(); - } - else if (type == col_type_Link) { - const LinkColumn& cl = table->get_column_link(link_column_index); - m_link_columns.push_back(&cl); - table = &cl.get_target_table(); - } - else if (type == col_type_BackLink) { - const BacklinkColumn& bl = table->get_column_backlink(link_column_index); - m_link_columns.push_back(&bl); - m_only_unary_links = false; - table = &bl.get_origin_table(); - } - } - - m_target_table = table; - } - - std::vector get_links(size_t index) - { - std::vector res; - get_links(index, res); - return res; - } - - size_t count_links(size_t row) - { - CountLinks counter; - map_links(row, counter); - return counter.result(); - } - - void map_links(size_t row, LinkMapFunction& lm) - { - map_links(0, row, lm); - } - - bool only_unary_links() const - { - return m_only_unary_links; - } - - const Table* base_table() const - { - return m_base_table; - } - - const Table* target_table() const - { - return m_target_table; - } - - std::vector m_link_columns; - -private: - void map_links(size_t column, size_t row, LinkMapFunction& lm) - { - bool last = (column + 1 == m_link_columns.size()); - ColumnType type = m_link_types[column]; - if (type == col_type_Link) { - const LinkColumn& cl = *static_cast(m_link_columns[column]); - size_t r = to_size_t(cl.get(row)); - if (r == 0) - return; - r--; // LinkColumn stores link to row N as N + 1 - if (last) { - bool continue2 = lm.consume(r); - if (!continue2) - return; - } - else - map_links(column + 1, r, lm); - } - else if (type == col_type_LinkList) { - const LinkListColumn& cll = *static_cast(m_link_columns[column]); - ConstLinkViewRef lvr = cll.get(row); - for (size_t t = 0; t < lvr->size(); t++) { - size_t r = lvr->get(t).get_index(); - if (last) { - bool continue2 = lm.consume(r); - if (!continue2) - return; - } - else - map_links(column + 1, r, lm); - } - } - else if (type == col_type_BackLink) { - const BacklinkColumn& bl = *static_cast(m_link_columns[column]); - size_t count = bl.get_backlink_count(row); - for (size_t i = 0; i < count; ++i) { - size_t r = bl.get_backlink(row, i); - if (last) { - bool continue2 = lm.consume(r); - if (!continue2) - return; - } - else - map_links(column + 1, r, lm); - } - } - } - - - void get_links(size_t row, std::vector& result) - { - MakeLinkVector mlv = MakeLinkVector(result); - map_links(row, mlv); - } - - std::vector m_link_column_indexes; - std::vector m_link_types; - const Table* m_base_table = nullptr; - const Table* m_target_table = nullptr; - bool m_only_unary_links = true; - - template - friend Query compare(const Subexpr2&, const ConstRow&); -}; - -template -Query string_compare(const Columns& left, T right, bool case_insensitive); -template -Query string_compare(const Columns& left, const Columns& right, bool case_insensitive); - -template -Value make_value_for_link(bool only_unary_links, size_t size) -{ - Value value; - if (only_unary_links) { - REALM_ASSERT(size <= 1); - value.init(false, 1); - value.m_storage.set_null(0); - } - else { - value.init(true, size); - } - return value; -} - - -// If we add a new Realm type T and quickly want Query support for it, then simply inherit from it like -// `template <> class Columns : public SimpleQuerySupport` and you're done. Any operators of the set -// { ==, >=, <=, !=, >, < } that are supported by T will be supported by the "query expression syntax" -// automatically. NOTE: This method of Query support will be slow because it goes through Table::get. -// To get faster Query support, either add SequentialGetter support (faster) or create a query_engine.hpp -// node for it (super fast). - -template -class SimpleQuerySupport : public Subexpr2 { -public: - SimpleQuerySupport(size_t column, const Table* table, std::vector links = {}) - : m_column_ndx(column) - , m_link_map(table, std::move(links)) - { - m_column = &m_link_map.target_table()->get_column_base(m_column_ndx); - } - - bool is_nullable() const noexcept - { - return m_link_map.base_table()->is_nullable(m_column->get_column_index()); - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - void set_base_table(const Table* table) override - { - if (table != get_base_table()) { - m_link_map.set_base_table(table); - m_column = &m_link_map.target_table()->get_column_base(m_column_ndx); - } - } - - void evaluate(size_t index, ValueBase& destination) override - { - Value& d = static_cast&>(destination); - size_t col = column_ndx(); - - if (links_exist()) { - std::vector links = m_link_map.get_links(index); - Value v = make_value_for_link(m_link_map.only_unary_links(), links.size()); - - for (size_t t = 0; t < links.size(); t++) { - size_t link_to = links[t]; - v.m_storage.set(t, m_link_map.target_table()->template get(col, link_to)); - } - destination.import(v); - } - else { - // Not a link column - const Table* target_table = m_link_map.target_table(); - for (size_t t = 0; t < destination.m_values && index + t < target_table->size(); t++) { - d.m_storage.set(t, target_table->get(col, index + t)); - } - } - } - - bool links_exist() const - { - return m_link_map.m_link_columns.size() > 0; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches = nullptr) const override - { - return make_subexpr>(static_cast&>(*this), patches); - } - - SimpleQuerySupport(SimpleQuerySupport const& other, QueryNodeHandoverPatches* patches) - : Subexpr2(other) - , m_column_ndx(other.m_column_ndx) - , m_column(other.m_column) - , m_link_map(other.m_link_map, patches) - { - if (patches && m_column) { - m_column_ndx = column_ndx(); - m_column = nullptr; - } - } - - size_t column_ndx() const - { - return m_column->get_column_index(); - } - -private: - // Column index of payload column of m_table - mutable size_t m_column_ndx; - const ColumnBase* m_column; - LinkMap m_link_map; -}; - - -template <> -class Columns : public SimpleQuerySupport { - using SimpleQuerySupport::SimpleQuerySupport; -}; - -template <> -class Columns : public SimpleQuerySupport { - using SimpleQuerySupport::SimpleQuerySupport; -}; - - -template <> -class Columns : public SimpleQuerySupport { -public: - using SimpleQuerySupport::SimpleQuerySupport; - - Query equal(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query equal(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } - - Query not_equal(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query not_equal(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } - - Query begins_with(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query begins_with(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } - - Query ends_with(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query ends_with(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } - - Query contains(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query contains(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } - - Query like(StringData sd, bool case_sensitive = true) - { - return string_compare(*this, sd, case_sensitive); - } - - Query like(const Columns& col, bool case_sensitive = true) - { - return string_compare(*this, col, case_sensitive); - } -}; - - -template -Query string_compare(const Columns& left, T right, bool case_sensitive) -{ - StringData sd(right); - if (case_sensitive) - return create(sd, left); - else - return create(sd, left); -} - -template -Query string_compare(const Columns& left, const Columns& right, bool case_sensitive) -{ - if (case_sensitive) - return make_expression>(right.clone(), left.clone()); - else - return make_expression>(right.clone(), left.clone()); -} - -// Columns == Columns -inline Query operator==(const Columns& left, const Columns& right) -{ - return string_compare(left, right, true); -} - -// Columns != Columns -inline Query operator!=(const Columns& left, const Columns& right) -{ - return string_compare(left, right, true); -} - -// String == Columns -template -Query operator==(T left, const Columns& right) -{ - return operator==(right, left); -} - -// String != Columns -template -Query operator!=(T left, const Columns& right) -{ - return operator!=(right, left); -} - -// Columns == String -template -Query operator==(const Columns& left, T right) -{ - return string_compare(left, right, true); -} - -// Columns != String -template -Query operator!=(const Columns& left, T right) -{ - return string_compare(left, right, true); -} - - -inline Query operator==(const Columns& left, BinaryData right) -{ - return create(right, left); -} - -inline Query operator==(BinaryData left, const Columns& right) -{ - return create(left, right); -} - -inline Query operator!=(const Columns& left, BinaryData right) -{ - return create(right, left); -} - -inline Query operator!=(BinaryData left, const Columns& right) -{ - return create(left, right); -} - - -// This class is intended to perform queries on the *pointers* of links, contrary to performing queries on *payload* -// in linked-to tables. Queries can be "find first link that points at row X" or "find first null-link". Currently -// only "find first null link" and "find first non-null link" is supported. More will be added later. When we add -// more, I propose to remove the template argument from this class and instead template it by -// a criteria-class (like the FindNullLinks class below in find_first()) in some generalized fashion. -template -class UnaryLinkCompare : public Expression { -public: - UnaryLinkCompare(LinkMap lm) - : m_link_map(std::move(lm)) - { - } - - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - } - - // Return main table of query (table on which table->where()... is invoked). Note that this is not the same as - // any linked-to payload tables - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - size_t find_first(size_t start, size_t end) const override - { - for (; start < end;) { - std::vector l = m_link_map.get_links(start); - // We have found a Link which is NULL, or LinkList with 0 entries. Return it as match. - - FindNullLinks fnl; - m_link_map.map_links(start, fnl); - if (fnl.m_has_link == has_links) - return start; - - start++; - } - - return not_found; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new UnaryLinkCompare(*this, patches)); - } - -private: - UnaryLinkCompare(const UnaryLinkCompare& other, QueryNodeHandoverPatches* patches = nullptr) - : Expression(other) - , m_link_map(other.m_link_map, patches) - { - } - - mutable LinkMap m_link_map; -}; - -class LinkCount : public Subexpr2 { -public: - LinkCount(LinkMap link_map) - : m_link_map(std::move(link_map)) - { - } - LinkCount(LinkCount const& other, QueryNodeHandoverPatches* patches) - : Subexpr2(other) - , m_link_map(other.m_link_map, patches) - { - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr(*this, patches); - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - } - - void evaluate(size_t index, ValueBase& destination) override - { - size_t count = m_link_map.count_links(index); - destination.import(Value(false, 1, count)); - } - -private: - LinkMap m_link_map; -}; - -struct ConstantRowValueHandoverPatch : public QueryNodeHandoverPatch { - std::unique_ptr row_patch; -}; - -class ConstantRowValue : public Subexpr2 { -public: - ConstantRowValue(const ConstRow& row) - : m_row(row) - { - } - - void set_base_table(const Table*) override - { - } - const Table* get_base_table() const override - { - return nullptr; - } - - void evaluate(size_t, ValueBase& destination) override - { - if (m_row.is_attached()) { - Value v(RowIndex(m_row.get_index())); - destination.import(v); - } - else { - Value v(RowIndex::Detached); - destination.import(v); - } - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new ConstantRowValue(*this, patches)); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - REALM_ASSERT(patches.size()); - std::unique_ptr abstract_patch = std::move(patches.back()); - patches.pop_back(); - - auto patch = dynamic_cast(abstract_patch.get()); - REALM_ASSERT(patch); - - m_row.apply_and_consume_patch(patch->row_patch, group); - } - -private: - ConstantRowValue(const ConstantRowValue& source, QueryNodeHandoverPatches* patches) - : m_row(patches ? ConstRow() : source.m_row) - { - if (!patches) - return; - - std::unique_ptr patch(new ConstantRowValueHandoverPatch); - ConstRow::generate_patch(source.m_row, patch->row_patch); - patches->emplace_back(patch.release()); - } - - ConstRow m_row; -}; - -template -class SubColumns; - -// This is for LinkList and BackLink too since they're declared as typedefs of Link. -template <> -class Columns : public Subexpr2 { -public: - Query is_null() - { - if (m_link_map.m_link_columns.size() > 1) - throw std::runtime_error("Combining link() and is_null() is currently not supported"); - // Todo, it may be useful to support the above, but we would need to figure out an intuitive behaviour - return make_expression>(m_link_map); - } - - Query is_not_null() - { - if (m_link_map.m_link_columns.size() > 1) - throw std::runtime_error("Combining link() and is_not_null() is currently not supported"); - // Todo, it may be useful to support the above, but we would need to figure out an intuitive behaviour - return make_expression>(m_link_map); - } - - LinkCount count() const - { - return LinkCount(m_link_map); - } - - template - SubColumns column(size_t column_ndx) const - { - return SubColumns(Columns(column_ndx, m_link_map.target_table()), m_link_map); - } - - const LinkMap& link_map() const - { - return m_link_map; - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr>(*this, patches); - } - - void evaluate(size_t index, ValueBase& destination) override - { - std::vector links = m_link_map.get_links(index); - Value v = make_value_for_link(m_link_map.only_unary_links(), links.size()); - - for (size_t t = 0; t < links.size(); t++) { - v.m_storage.set(t, RowIndex(links[t])); - } - destination.import(v); - } - - Columns(const Columns& other, QueryNodeHandoverPatches* patches) - : Subexpr2(other) - , m_link_map(other.m_link_map, patches) - { - } - -private: - Columns(size_t column_ndx, const Table* table, const std::vector& links = {}) - : m_link_map(table, links) - { - static_cast(column_ndx); - } - - LinkMap m_link_map; - friend class Table; -}; - - -template -Query compare(const Subexpr2& left, const ConstRow& row) -{ - static_assert(std::is_same::value || std::is_same::value, - "Links can only be compared for equality."); - const Columns* column = dynamic_cast*>(&left); - if (column) { - const LinkMap& link_map = column->link_map(); - REALM_ASSERT(link_map.target_table() == row.get_table() || !row.is_attached()); -#ifdef REALM_OLDQUERY_FALLBACK - if (link_map.m_link_columns.size() == 1) { - // We can fall back to Query::links_to for != and == operations on links, but only - // for == on link lists. This is because negating query.links_to() is equivalent to - // to "ALL linklist != row" rather than the "ANY linklist != row" semantics we're after. - if (link_map.m_link_types[0] == col_type_Link || - (link_map.m_link_types[0] == col_type_LinkList && std::is_same::value)) { - const Table* t = column->get_base_table(); - Query query(*t); - - if (std::is_same::value) { - // Negate the following `links_to`. - query.Not(); - } - query.links_to(link_map.m_link_column_indexes[0], row); - return query; - } - } -#endif - } - return make_expression>(left.clone(), make_subexpr(row)); -} - -inline Query operator==(const Subexpr2& left, const ConstRow& row) -{ - return compare(left, row); -} -inline Query operator!=(const Subexpr2& left, const ConstRow& row) -{ - return compare(left, row); -} -inline Query operator==(const ConstRow& row, const Subexpr2& right) -{ - return compare(right, row); -} -inline Query operator!=(const ConstRow& row, const Subexpr2& right) -{ - return compare(right, row); -} - -template -Query compare(const Subexpr2& left, null) -{ - static_assert(std::is_same::value || std::is_same::value, - "Links can only be compared for equality."); - return make_expression>(left.clone(), make_subexpr>()); -} - -inline Query operator==(const Subexpr2& left, null) -{ - return compare(left, null()); -} -inline Query operator!=(const Subexpr2& left, null) -{ - return compare(left, null()); -} -inline Query operator==(null, const Subexpr2& right) -{ - return compare(right, null()); -} -inline Query operator!=(null, const Subexpr2& right) -{ - return compare(right, null()); -} - - -template -class Columns : public Subexpr2 { -public: - using ColType = typename ColumnTypeTraits::column_type; - - Columns(size_t column, const Table* table, std::vector links = {}) - : m_link_map(table, std::move(links)) - , m_column(column) - , m_nullable(m_link_map.target_table()->is_nullable(m_column)) - { - } - - Columns(const Columns& other, QueryNodeHandoverPatches* patches = nullptr) - : m_link_map(other.m_link_map, patches) - , m_column(other.m_column) - , m_nullable(other.m_nullable) - { - if (!other.m_sg) - return; - - if (patches) { - m_column = other.get_column_base().get_column_index(); - } - else { - if (m_nullable && std::is_same::value) { - init(&other.get_column_base()); - } - else { - init(&other.get_column_base()); - } - } - } - - Columns& operator=(const Columns& other) - { - if (this != &other) { - m_link_map = other.m_link_map; - m_sg.reset(); - m_column = other.m_column; - m_nullable = other.m_nullable; - } - return *this; - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr>(*this, patches); - } - - // See comment in base class - void set_base_table(const Table* table) override - { - if (m_sg && table == get_base_table()) - return; - - m_link_map.set_base_table(table); - m_nullable = m_link_map.target_table()->is_nullable(m_column); - - const ColumnBase* c = &m_link_map.target_table()->get_column_base(m_column); - if (m_nullable && std::is_same::value) { - init(c); - } - else { - init(c); - } - } - - template - void init(const ColumnBase* c) - { - REALM_ASSERT_DEBUG(dynamic_cast(c)); - if (m_sg == nullptr) { - m_sg.reset(new SequentialGetter()); - } - static_cast&>(*m_sg).init(static_cast(c)); - } - - // Recursively fetch tables of columns in expression tree. Used when user first builds a stand-alone expression - // and binds it to a Query at a later time - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - template - void evaluate_internal(size_t index, ValueBase& destination) - { - REALM_ASSERT_DEBUG(m_sg.get()); - REALM_ASSERT_DEBUG(dynamic_cast*>(m_sg.get())); - - using U = typename ColType2::value_type; - auto sgc = static_cast*>(m_sg.get()); - REALM_ASSERT_DEBUG(sgc->m_column); - - if (links_exist()) { - // LinkList with more than 0 values. Create Value with payload for all fields - - std::vector links = m_link_map.get_links(index); - auto v = make_value_for_link::type>(m_link_map.only_unary_links(), - links.size()); - - for (size_t t = 0; t < links.size(); t++) { - size_t link_to = links[t]; - sgc->cache_next(link_to); - - if (sgc->m_column->is_null(link_to)) - v.m_storage.set_null(t); - else - v.m_storage.set(t, sgc->get_next(link_to)); - } - destination.import(v); - } - else { - // Not a Link column - // make sequential getter load the respective leaf to access data at column row 'index' - sgc->cache_next(index); - size_t colsize = sgc->m_column->size(); - - // Now load `ValueBase::default_size` rows from from the leaf into m_storage. If it's an integer - // leaf, then it contains the method get_chunk() which copies these values in a super fast way (first - // case of the `if` below. Otherwise, copy the values one by one in a for-loop (the `else` case). - if (std::is_same::value && index + ValueBase::default_size <= sgc->m_leaf_end) { - Value v; - - // If you want to modify 'default_size' then update Array::get_chunk() - REALM_ASSERT_3(ValueBase::default_size, ==, 8); - - auto sgc_2 = static_cast*>(m_sg.get()); - sgc_2->m_leaf_ptr->get_chunk( - index - sgc->m_leaf_start, - static_cast*>(static_cast(&v))->m_storage.m_first); - - destination.import(v); - } - else { - size_t rows = colsize - index; - if (rows > ValueBase::default_size) - rows = ValueBase::default_size; - Value::type> v(false, rows); - - for (size_t t = 0; t < rows; t++) - v.m_storage.set(t, sgc->get_next(index + t)); - - destination.import(v); - } - } - } - - // Load values from Column into destination - void evaluate(size_t index, ValueBase& destination) override - { - if (m_nullable && std::is_same::value) { - evaluate_internal(index, destination); - } - else { - evaluate_internal(index, destination); - } - } - - bool links_exist() const - { - return m_link_map.m_link_columns.size() > 0; - } - - bool is_nullable() const - { - return m_nullable; - } - - size_t column_ndx() const noexcept - { - return m_sg ? get_column_base().get_column_index() : m_column; - } - -private: - LinkMap m_link_map; - - // Fast (leaf caching) value getter for payload column (column in table on which query condition is executed) - std::unique_ptr m_sg; - - // Column index of payload column of m_table - size_t m_column; - - // set to false by default for stand-alone Columns declaration that are not yet associated with any table - // or oclumn. Call init() to update it or use a constructor that takes table + column index as argument. - bool m_nullable = false; - - const ColumnBase& get_column_base() const noexcept - { - if (m_nullable && std::is_same::value) - return *static_cast&>(*m_sg).m_column; - else - return *static_cast&>(*m_sg).m_column; - } -}; - -template -class SubColumnAggregate; -namespace aggregate_operations { -template -class Minimum; -template -class Maximum; -template -class Sum; -template -class Average; -} - -template -class SubColumns : public Subexpr { -public: - SubColumns(Columns column, LinkMap link_map) - : m_column(std::move(column)) - , m_link_map(std::move(link_map)) - { - } - - std::unique_ptr clone(QueryNodeHandoverPatches*) const override - { - return make_subexpr>(*this); - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - m_column.set_base_table(m_link_map.target_table()); - } - - void evaluate(size_t, ValueBase&) override - { - // SubColumns can only be used in an expression in conjunction with its aggregate methods. - REALM_ASSERT(false); - } - - SubColumnAggregate> min() const - { - return {m_column, m_link_map}; - } - - SubColumnAggregate> max() const - { - return {m_column, m_link_map}; - } - - SubColumnAggregate> sum() const - { - return {m_column, m_link_map}; - } - - SubColumnAggregate> average() const - { - return {m_column, m_link_map}; - } - -private: - Columns m_column; - LinkMap m_link_map; -}; - -template -class SubColumnAggregate : public Subexpr2 { -public: - SubColumnAggregate(Columns column, LinkMap link_map) - : m_column(std::move(column)) - , m_link_map(std::move(link_map)) - { - } - SubColumnAggregate(SubColumnAggregate const& other, QueryNodeHandoverPatches* patches) - : m_column(other.m_column, patches) - , m_link_map(other.m_link_map, patches) - { - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr(*this, patches); - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - m_column.set_base_table(m_link_map.target_table()); - } - - void evaluate(size_t index, ValueBase& destination) override - { - std::vector links = m_link_map.get_links(index); - std::sort(links.begin(), links.end()); - - Operation op; - for (size_t link_index = 0; link_index < links.size();) { - Value value; - size_t link = links[link_index]; - m_column.evaluate(link, value); - - // Columns::evaluate fetches values in chunks of ValueBase::default_size. Process all values - // within the chunk that came from rows that we link to. - const auto& value_storage = value.m_storage; - for (size_t value_index = 0; value_index < value.m_values;) { - if (!value_storage.is_null(value_index)) { - op.accumulate(value_storage[value_index]); - } - if (++link_index >= links.size()) { - break; - } - - size_t previous_link = link; - link = links[link_index]; - value_index += link - previous_link; - } - } - if (op.is_null()) { - destination.import(Value(false, 1, null())); - } - else { - destination.import(Value(false, 1, op.result())); - } - } - -private: - Columns m_column; - LinkMap m_link_map; -}; - -struct SubQueryCountHandoverPatch : QueryNodeHandoverPatch { - QueryHandoverPatch m_query; -}; - -class SubQueryCount : public Subexpr2 { -public: - SubQueryCount(Query q, LinkMap link_map) - : m_query(std::move(q)) - , m_link_map(std::move(link_map)) - { - } - - const Table* get_base_table() const override - { - return m_link_map.base_table(); - } - - void set_base_table(const Table* table) override - { - m_link_map.set_base_table(table); - } - - void evaluate(size_t index, ValueBase& destination) override - { - std::vector links = m_link_map.get_links(index); - std::sort(links.begin(), links.end()); - - size_t count = std::accumulate(links.begin(), links.end(), 0, [this](size_t running_count, size_t link) { - return running_count + m_query.count(link, link + 1, 1); - }); - - destination.import(Value(false, 1, count)); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - if (patches) - return std::unique_ptr(new SubQueryCount(*this, patches)); - - return make_subexpr(*this); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - REALM_ASSERT(patches.size()); - std::unique_ptr abstract_patch = std::move(patches.back()); - patches.pop_back(); - - auto patch = dynamic_cast(abstract_patch.get()); - REALM_ASSERT(patch); - - m_query.apply_patch(patch->m_query, group); - } - -private: - SubQueryCount(const SubQueryCount& other, QueryNodeHandoverPatches* patches) - : m_link_map(other.m_link_map, patches) - { - std::unique_ptr patch(new SubQueryCountHandoverPatch); - m_query = Query(other.m_query, patch->m_query, ConstSourcePayload::Copy); - patches->emplace_back(patch.release()); - } - - Query m_query; - LinkMap m_link_map; -}; - -// The unused template parameter is a hack to avoid a circular dependency between table.hpp and query_expression.hpp. -template -class SubQuery { -public: - SubQuery(Columns link_column, Query query) - : m_query(std::move(query)) - , m_link_map(link_column.link_map()) - { - REALM_ASSERT(m_link_map.target_table() == m_query.get_table()); - } - - SubQueryCount count() const - { - return SubQueryCount(m_query, m_link_map); - } - -private: - Query m_query; - LinkMap m_link_map; -}; - -namespace aggregate_operations { -template -class BaseAggregateOperation { - static_assert(std::is_same::value || std::is_same::value || std::is_same::value, - "Numeric aggregates can only be used with subcolumns of numeric types"); - -public: - using ResultType = R; - - void accumulate(T value) - { - m_count++; - m_result = Derived::apply(m_result, value); - } - - bool is_null() const - { - return m_count == 0; - } - ResultType result() const - { - return m_result; - } - -protected: - size_t m_count = 0; - ResultType m_result = Derived::initial_value(); -}; - -template -class Minimum : public BaseAggregateOperation> { -public: - static T initial_value() - { - return std::numeric_limits::max(); - } - static T apply(T a, T b) - { - return std::min(a, b); - } -}; - -template -class Maximum : public BaseAggregateOperation> { -public: - static T initial_value() - { - return std::numeric_limits::min(); - } - static T apply(T a, T b) - { - return std::max(a, b); - } -}; - -template -class Sum : public BaseAggregateOperation> { -public: - static T initial_value() - { - return T(); - } - static T apply(T a, T b) - { - return a + b; - } - bool is_null() const - { - return false; - } -}; - -template -class Average : public BaseAggregateOperation, double> { - using Base = BaseAggregateOperation, double>; - -public: - static double initial_value() - { - return 0; - } - static double apply(double a, T b) - { - return a + b; - } - double result() const - { - return Base::m_result / Base::m_count; - } -}; -} - -template -class UnaryOperator : public Subexpr2 { -public: - UnaryOperator(std::unique_ptr left) - : m_left(std::move(left)) - { - } - - UnaryOperator(const UnaryOperator& other, QueryNodeHandoverPatches* patches) - : m_left(other.m_left->clone(patches)) - { - } - - UnaryOperator& operator=(const UnaryOperator& other) - { - if (this != &other) { - m_left = other.m_left->clone(); - } - return *this; - } - - UnaryOperator(UnaryOperator&&) = default; - UnaryOperator& operator=(UnaryOperator&&) = default; - - // See comment in base class - void set_base_table(const Table* table) override - { - m_left->set_base_table(table); - } - - // Recursively fetch tables of columns in expression tree. Used when user first builds a stand-alone expression - // and - // binds it to a Query at a later time - const Table* get_base_table() const override - { - return m_left->get_base_table(); - } - - // destination = operator(left) - void evaluate(size_t index, ValueBase& destination) override - { - Value result; - Value left; - m_left->evaluate(index, left); - result.template fun(&left); - destination.import(result); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr(*this, patches); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_left->apply_handover_patch(patches, group); - } - -private: - typedef typename oper::type T; - std::unique_ptr m_left; -}; - - -template -class Operator : public Subexpr2 { -public: - Operator(std::unique_ptr left, std::unique_ptr right) - : m_left(std::move(left)) - , m_right(std::move(right)) - { - } - - Operator(const Operator& other, QueryNodeHandoverPatches* patches) - : m_left(other.m_left->clone(patches)) - , m_right(other.m_right->clone(patches)) - { - } - - Operator& operator=(const Operator& other) - { - if (this != &other) { - m_left = other.m_left->clone(); - m_right = other.m_right->clone(); - } - return *this; - } - - Operator(Operator&&) = default; - Operator& operator=(Operator&&) = default; - - // See comment in base class - void set_base_table(const Table* table) override - { - m_left->set_base_table(table); - m_right->set_base_table(table); - } - - // Recursively fetch tables of columns in expression tree. Used when user first builds a stand-alone expression - // and - // binds it to a Query at a later time - const Table* get_base_table() const override - { - const Table* l = m_left->get_base_table(); - const Table* r = m_right->get_base_table(); - - // Queries do not support multiple different tables; all tables must be the same. - REALM_ASSERT(l == nullptr || r == nullptr || l == r); - - // nullptr pointer means expression which isn't yet associated with any table, or is a Value - return l ? l : r; - } - - // destination = operator(left, right) - void evaluate(size_t index, ValueBase& destination) override - { - Value result; - Value left; - Value right; - m_left->evaluate(index, left); - m_right->evaluate(index, right); - result.template fun(&left, &right); - destination.import(result); - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return make_subexpr(*this, patches); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_right->apply_handover_patch(patches, group); - m_left->apply_handover_patch(patches, group); - } - -private: - typedef typename oper::type T; - std::unique_ptr m_left; - std::unique_ptr m_right; -}; - - -template -class Compare : public Expression { -public: - Compare(std::unique_ptr left, std::unique_ptr right) - : m_left(std::move(left)) - , m_right(std::move(right)) - { - } - - // See comment in base class - void set_base_table(const Table* table) override - { - m_left->set_base_table(table); - m_right->set_base_table(table); - } - - // Recursively fetch tables of columns in expression tree. Used when user first builds a stand-alone expression - // and - // binds it to a Query at a later time - const Table* get_base_table() const override - { - const Table* l = m_left->get_base_table(); - const Table* r = m_right->get_base_table(); - - // All main tables in each subexpression of a query (table.columns() or table.link()) must be the same. - REALM_ASSERT(l == nullptr || r == nullptr || l == r); - - // nullptr pointer means expression which isn't yet associated with any table, or is a Value - return l ? l : r; - } - - size_t find_first(size_t start, size_t end) const override - { - size_t match; - Value right; - Value left; - - for (; start < end;) { - m_left->evaluate(start, left); - m_right->evaluate(start, right); - match = Value::template compare(&left, &right); - - if (match != not_found && match + start < end) - return start + match; - - size_t rows = - (left.m_from_link_list || right.m_from_link_list) ? 1 : minimum(right.m_values, left.m_values); - start += rows; - } - - return not_found; // no match - } - - std::unique_ptr clone(QueryNodeHandoverPatches* patches) const override - { - return std::unique_ptr(new Compare(*this, patches)); - } - - void apply_handover_patch(QueryNodeHandoverPatches& patches, Group& group) override - { - m_right->apply_handover_patch(patches, group); - m_left->apply_handover_patch(patches, group); - } - -private: - Compare(const Compare& other, QueryNodeHandoverPatches* patches) - : m_left(other.m_left->clone(patches)) - , m_right(other.m_right->clone(patches)) - { - } - - std::unique_ptr m_left; - std::unique_ptr m_right; -}; -} -#endif // REALM_QUERY_EXPRESSION_HPP diff --git a/Example/Pods/Realm/include/core/realm/realm_nmmintrin.h b/Example/Pods/Realm/include/core/realm/realm_nmmintrin.h deleted file mode 100644 index 8144da6..0000000 --- a/Example/Pods/Realm/include/core/realm/realm_nmmintrin.h +++ /dev/null @@ -1,182 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_NMMINTRIN_H -#define REALM_NMMINTRIN_H - -/* - We must support runtime detection of CPU support of SSE when distributing Realm as a closed source library. - - This is a problem on gcc and llvm: To use SSE intrinsics we need to pass -msse on the command line (to get offered - __builtin_ accessors used by intrinsics functions). However, the -msse flag allows gcc to emit SSE instructions - in its code generation/optimization. This is unwanted because the binary would crash on non-SSE CPUs. - - Since there exists no flag in gcc that enables intrinsics but probits SSE in code generation, we define our - own intrinsics to be assembled by the back end assembler and omit passing -msse to gcc. -*/ - -#ifndef _MSC_VER - -#ifdef REALM_COMPILER_SSE -#include // SSE2 (using __m128i) -#endif - -namespace realm { - -#if 0 -#ifdef REALM_COMPILER_AVX -typedef float __m256 __attribute__((__vector_size__(32), __may_alias__)); -typedef double __m256d __attribute__((__vector_size__(32), __may_alias__)); - -const int _CMP_EQ_OQ = 0x00; // Equal (ordered, non-signaling) -const int _CMP_NEQ_OQ = 0x0c; // Not-equal (ordered, non-signaling) -const int _CMP_LT_OQ = 0x11; // Less-than (ordered, non-signaling) -const int _CMP_LE_OQ = 0x12; // Less-than-or-equal (ordered, non-signaling) -const int _CMP_GE_OQ = 0x1d; // Greater-than-or-equal (ordered, non-signaling) -const int _CMP_GT_OQ = 0x1e; // Greater-than (ordered, non-signaling) - - -template -static int movemask_cmp_ps(__m256* y1, __m256* y2) -{ - int ret; - __asm__("vmovaps %0, %%ymm0" : : "m"(*y1) : "%xmm0" ); - __asm__("vmovaps %0, %%ymm1" : : "m"(*y2) : "%xmm1" ); - __asm__("vcmpps %0, %%ymm0, %%ymm1, %%ymm0" : : "I"(op) : "%xmm0" ); - __asm__("vmovmskps %%ymm0, %0" : "=r"(ret) : : ); - return ret; -} - -template -static inline int movemask_cmp_pd(__m256d* y1, __m256d* y2) -{ - int ret; - __asm__("vmovapd %0, %%ymm0" : : "m"(*y1) : "%xmm0" ); - __asm__("vmovapd %0, %%ymm1" : : "m"(*y2) : "%xmm1" ); - __asm__("vcmppd %0, %%ymm0, %%ymm1, %%ymm0" : : "I"(op) : "%xmm0" ); - __asm__("vmovmskpd %%ymm0, %0" : "=r"(ret) : : ); - return ret; -} - - - -static inline int movemask_cmp_ps(__m256* y1, __m256* y2, int op) -{ - // todo, use constexpr; - if (op == _CMP_EQ_OQ) - return movemask_cmp_ps<_CMP_NEQ_OQ>(y1, y2); - else if (op == _CMP_NEQ_OQ) - return movemask_cmp_ps<_CMP_NEQ_OQ>(y1, y2); - else if (op == _CMP_LT_OQ) - return movemask_cmp_ps<_CMP_LT_OQ>(y1, y2); - else if (op == _CMP_LE_OQ) - return movemask_cmp_ps<_CMP_LE_OQ>(y1, y2); - else if (op == _CMP_GE_OQ) - return movemask_cmp_ps<_CMP_GE_OQ>(y1, y2); - else if (op == _CMP_GT_OQ) - return movemask_cmp_ps<_CMP_GT_OQ>(y1, y2); - - REALM_ASSERT(false); - return 0; -} - -static inline int movemask_cmp_pd(__m256d* y1, __m256d* y2, int op) -{ - // todo, use constexpr; - if (op == _CMP_EQ_OQ) - return movemask_cmp_pd<_CMP_NEQ_OQ>(y1, y2); - else if (op == _CMP_NEQ_OQ) - return movemask_cmp_pd<_CMP_NEQ_OQ>(y1, y2); - else if (op == _CMP_LT_OQ) - return movemask_cmp_pd<_CMP_LT_OQ>(y1, y2); - else if (op == _CMP_LE_OQ) - return movemask_cmp_pd<_CMP_LE_OQ>(y1, y2); - else if (op == _CMP_GE_OQ) - return movemask_cmp_pd<_CMP_GE_OQ>(y1, y2); - else if (op == _CMP_GT_OQ) - return movemask_cmp_pd<_CMP_GT_OQ>(y1, y2); - - REALM_ASSERT(false); - return 0; -} - - -#endif -#endif - -// Instructions introduced by SSE 3 and 4.2 -static inline __m128i _mm_cmpgt_epi64(__m128i xmm1, __m128i xmm2) -{ - __asm__("pcmpgtq %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i _mm_cmpeq_epi64(__m128i xmm1, __m128i xmm2) -{ - __asm__("pcmpeqq %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_min_epi8(__m128i xmm1, __m128i xmm2) -{ - __asm__("pminsb %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_max_epi8(__m128i xmm1, __m128i xmm2) -{ - __asm__("pmaxsb %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_max_epi32(__m128i xmm1, __m128i xmm2) -{ - __asm__("pmaxsd %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_min_epi32(__m128i xmm1, __m128i xmm2) -{ - __asm__("pminsd %1, %0" : "+x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_cvtepi8_epi16(__m128i xmm2) -{ - __m128i xmm1; - __asm__("pmovsxbw %1, %0" : "=x" (xmm1) : "xm" (xmm2) : "xmm1"); - return xmm1; -} -static inline __m128i __attribute__((always_inline)) _mm_cvtepi16_epi32(__m128i xmm2) -{ - __m128i xmm1; - asm("pmovsxwd %1, %0" : "=x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -static inline __m128i __attribute__((always_inline)) _mm_cvtepi32_epi64(__m128i xmm2) -{ - __m128i xmm1; - __asm__("pmovsxdq %1, %0" : "=x" (xmm1) : "xm" (xmm2)); - return xmm1; -} - -} // namespace realm - -#endif -#endif diff --git a/Example/Pods/Realm/include/core/realm/replication.hpp b/Example/Pods/Realm/include/core/realm/replication.hpp deleted file mode 100644 index 857ab2a..0000000 --- a/Example/Pods/Realm/include/core/realm/replication.hpp +++ /dev/null @@ -1,540 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_REPLICATION_HPP -#define REALM_REPLICATION_HPP - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace realm { -namespace util { -class Logger; -} - -// FIXME: Be careful about the possibility of one modification function being called by another where both do -// transaction logging. - -// FIXME: The current table/subtable selection scheme assumes that a TableRef of a subtable is not accessed after any -// modification of one of its ancestor tables. - -// FIXME: Checking on same Table* requires that ~Table checks and nullifies on match. Another option would be to store -// m_selected_table as a TableRef. Yet another option would be to assign unique identifiers to each Table instance via -// Allocator. Yet another option would be to explicitely invalidate subtables recursively when parent is modified. - -/// Replication is enabled by passing an instance of an implementation of this -/// class to the SharedGroup constructor. -class Replication : public _impl::TransactLogConvenientEncoder, protected _impl::TransactLogStream { -public: - // Be sure to keep this type aligned with what is actually used in - // SharedGroup. - using version_type = _impl::History::version_type; - using InputStream = _impl::NoCopyInputStream; - class TransactLogApplier; - class Interrupted; // Exception - class SimpleIndexTranslator; - - virtual std::string get_database_path() = 0; - - /// Called during construction of the associated SharedGroup object. - /// - /// \param shared_group The assocoated SharedGroup object. - virtual void initialize(SharedGroup& shared_group) = 0; - - /// Called by the associated SharedGroup object when a session is - /// initiated. A *session* is a sequence of of temporally overlapping - /// accesses to a specific Realm file, where each access consists of a - /// SharedGroup object through which the Realm file is open. Session - /// initiation occurs during the first opening of the Realm file within such - /// a session. - /// - /// Session initiation fails if this function throws. - /// - /// \param version The current version of the associated Realm. Out-of-Realm - /// history implementation can use this to trim off history entries that - /// were successfully added to the history, but for which the corresponding - /// subsequent commits on the Realm file failed. - /// - /// The default implementation does nothing. - virtual void initiate_session(version_type version) = 0; - - /// Called by the associated SharedGroup object when a session is - /// terminated. See initiate_session() for the definition of a - /// session. Session termination occurs upon closing the Realm through the - /// last SharedGroup object within the session. - /// - /// The default implementation does nothing. - virtual void terminate_session() noexcept = 0; - - /// \defgroup replication_transactions - //@{ - - /// From the point of view of the Replication class, a transaction is - /// initiated when, and only when the associated SharedGroup object calls - /// initiate_transact() and the call is successful. The associated - /// SharedGroup object must terminate every initiated transaction either by - /// calling finalize_commit() or by calling abort_transact(). It may only - /// call finalize_commit(), however, after calling prepare_commit(), and - /// only when prepare_commit() succeeds. If prepare_commit() fails (i.e., - /// throws) abort_transact() must still be called. - /// - /// The associated SharedGroup object is supposed to terminate a transaction - /// as soon as possible, and is required to terminate it before attempting - /// to initiate a new one. - /// - /// initiate_transact() is called by the associated SharedGroup object as - /// part of the initiation of a transaction, and at a time where the caller - /// has acquired exclusive write access to the local Realm. The Replication - /// implementation is allowed to perform "precursor transactions" on the - /// local Realm at this time. During the initiated transaction, the - /// associated SharedGroup object must inform the Replication object of all - /// modifying operations by calling set_value() and friends. - /// - /// FIXME: There is currently no way for implementations to perform - /// precursor transactions, since a regular transaction would cause a dead - /// lock when it tries to acquire a write lock. Consider giving access to - /// special non-locking precursor transactions via an extra argument to this - /// function. - /// - /// prepare_commit() serves as the first phase of a two-phase commit. This - /// function is called by the associated SharedGroup object immediately - /// before the commit operation on the local Realm. The associated - /// SharedGroup object will then, as the second phase, either call - /// finalize_commit() or abort_transact() depending on whether the commit - /// operation succeeded or not. The Replication implementation is allowed to - /// modify the Realm via the associated SharedGroup object at this time - /// (important to in-Realm histories). - /// - /// initiate_transact() and prepare_commit() are allowed to block the - /// calling thread if, for example, they need to communicate over the - /// network. If a calling thread is blocked in one of these functions, it - /// must be possible to interrupt the blocking operation by having another - /// thread call interrupt(). The contract is as follows: When interrupt() is - /// called, then any execution of initiate_transact() or prepare_commit(), - /// initiated before the interruption, must complete without blocking, or - /// the execution must be aborted by throwing an Interrupted exception. If - /// initiate_transact() or prepare_commit() throws Interrupted, it counts as - /// a failed operation. - /// - /// finalize_commit() is called by the associated SharedGroup object - /// immediately after a successful commit operation on the local Realm. This - /// happens at a time where modification of the Realm is no longer possible - /// via the associated SharedGroup object. In the case of in-Realm - /// histories, the changes are automatically finalized as part of the commit - /// operation performed by the caller prior to the invocation of - /// finalize_commit(), so in that case, finalize_commit() might not need to - /// do anything. - /// - /// abort_transact() is called by the associated SharedGroup object to - /// terminate a transaction without committing. That is, any transaction - /// that is not terminated by finalize_commit() is terminated by - /// abort_transact(). This could be due to an explicit rollback, or due to a - /// failed commit attempt. - /// - /// Note that finalize_commit() and abort_transact() are not allowed to - /// throw. - /// - /// \param current_version The version of the snapshot that the current - /// transaction is based on. - /// - /// \param history_updated Pass true only when the history has already been - /// updated to reflect the currently bound snapshot, such as when - /// _impl::History::update_early_from_top_ref() was called during the - /// transition from a read transaction to the current write transaction. - /// - /// \return prepare_commit() returns the version of the new snapshot - /// produced by the transaction. - /// - /// \throw Interrupted Thrown by initiate_transact() and prepare_commit() if - /// a blocking operation was interrupted. - - void initiate_transact(version_type current_version, bool history_updated); - version_type prepare_commit(version_type current_version); - void finalize_commit() noexcept; - void abort_transact() noexcept; - - //@} - - - /// Interrupt any blocking call to a function in this class. This function - /// may be called asyncronously from any thread, but it may not be called - /// from a system signal handler. - /// - /// Some of the public function members of this class may block, but only - /// when it it is explicitely stated in the documention for those functions. - /// - /// FIXME: Currently we do not state blocking behaviour for all the - /// functions that can block. - /// - /// After any function has returned with an interruption indication, the - /// only functions that may safely be called are abort_transact() and the - /// destructor. If a client, after having received an interruption - /// indication, calls abort_transact() and then clear_interrupt(), it may - /// resume normal operation through this Replication object. - void interrupt() noexcept; - - /// May be called by a client to reset this Replication object after an - /// interrupted transaction. It is not an error to call this function in a - /// situation where no interruption has occured. - void clear_interrupt() noexcept; - - /// Apply a changeset to the specified group. - /// - /// \param changeset The changes to be applied. - /// - /// \param group The destination group to apply the changeset to. - /// - /// \param logger If specified, and the library was compiled in debug mode, - /// then a line describing each individual operation is writted to the - /// specified logger. - /// - /// \throw BadTransactLog If the changeset could not be successfully parsed, - /// or ended prematurely. - static void apply_changeset(InputStream& changeset, Group& group, util::Logger* logger = nullptr); - - enum HistoryType { - /// No history available. No support for either continuous transactions - /// or inter-client synchronization. - hist_None = 0, - - /// Out-of-Realm history supporting continuous transactions. - hist_OutOfRealm = 1, - - /// In-Realm history supporting continuous transactions - /// (_impl::InRealmHistory). - hist_InRealm = 2, - - /// In-Realm history supporting continuous transactions and inter-client - /// synchronization (_impl::SyncHistory). - hist_Sync = 3 - }; - - /// Returns the type of history maintained by this Replication - /// implementation, or \ref hist_None if no history is maintained by it. - /// - /// This type is used to ensure that all session participants agree on - /// history type, and that the Realm file contains a compatible type of - /// history, at the beginning of a new session. - /// - /// As a special case, if there is no top array (Group::m_top) at the - /// beginning of a new session, then all history types (as returned by - /// get_history_type()) are allowed during that session. Note that this is - /// only possible if there was no preceding session, or if no transaction - /// was sucessfully comitted during any of the preceding sessions. As soon - /// as a transaction is successfully committed, the Realm contains at least - /// a top array, and from that point on, the history type is generally - /// fixed, although still subject to certain allowed changes (as mentioned - /// below). - /// - /// For the sake of backwards compatibility with older Realm files that does - /// not store any history type, the following rule shall apply: - /// - /// - If the top array of a Realm file (Group::m_top) does not contain a - /// history type, because it is too short, it shall be understood as - /// implicitely storing the type \ref hist_None. - /// - /// Note: In what follows, the meaning of *preceding session* is: The last - /// preceding session that modified the Realm by sucessfully committing a - /// new snapshot. - /// - /// Older Realm files do not store any history type, even when they were - /// last used with a history of type \ref hist_OutOfRealm. Howewver, since - /// such histories (\ref hist_OutOfRealm) are placed outside the Realm file, - /// and are transient (recreated at the beginning of each new session), a - /// new session is not obliged to use the same type of history (\ref - /// hist_OutOfRealm). For this reason, and to achieve further backwards - /// compatibility, the following rules are adopted: - /// - /// - At the beginning of a new session, if there is no stored history - /// type (no top array), or if the stored history type is \ref - /// hist_None, assume that the history type used during the preceding - /// session was \ref hist_None or \ref hist_OutOfRealm, or that there - /// was no preceding session. In all other cases, assume that the stored - /// history type is the type used during the preceding session. - /// - /// - When storing the history type, store \ref hist_None if the history - /// type used in the current session is \ref hist_None or \ref - /// hist_OutOfRealm. In all other cases, store the actual history type - /// used. - /// - /// It shall be allowed to switch to a \ref hist_InRealm history if the - /// stored history type is either \ref hist_None or \ref - /// hist_OutOfRealm. Fortunately, this can be done simply by adding a - /// history to the Realm file (of type \ref hist_InRealm), and that is - /// possible because a \ref hist_InRealm history is independent of any - /// history used in a previous session (as long as it was session-confined), - /// or whether any history was used at all. Conversely, if a \ref - /// hist_OutOfRealm history was used in the previous session, then the - /// contents of that history becomes obsolete at the end of the previous - /// session. - /// - /// On the other hand, as soon as a history of type \ref hist_InRealm is - /// added to a Realm file, that history type is binding for all subsequent - /// sessions. In theory, this constraint is not necessary, and a later - /// switch to \ref hist_None or \ref hist_OutOfRealm would be possible - /// because of the fact that the contents of the history becomes obsolete at - /// the end of the session, however, because the \ref hist_InRealm history - /// remains in the Realm file, there are practical complications, and for - /// that reason, such switching shall not be supported. - /// - /// The \ref hist_Sync history type can only be used if the stored history - /// type is also \ref hist_Sync, or when there is no top array - /// yet. Additionally, when the stored history type is \ref hist_Sync, then - /// all subsequent sesssions must have the same type. These restrictions - /// apply because such a history needs to be maintained persistently across - /// sessions. That is, the contents of such a history is not obsolete at the - /// end of the session, and is in general needed during subsequent sessions. - /// - /// In general, if there is no stored history type (no top array) at the - /// beginning of a new session, or if the stored type disagrees with what is - /// returned by get_history_type() (which is possible due to particular - /// allowed changes of history type), the actual history type (as returned - /// by get_history_type()) used during that session, must be stored in the - /// Realm during the first successfully committed transaction of that - /// session, if any are sucessfully committed. But note that there is still - /// no need to expand the top array to store the history type \ref - /// hist_None, due to the rule mentioned above. - /// - /// Due to the rules listed above, a new history type only actually needs to - /// be stored when the history type of the session (get_history_type()) is - /// neither \ref hist_None nor \ref hist_OutOfRealm, and only when that - /// differs from the stored history type, or if there is no top array at the - /// beginning of the session. - /// - /// Summary of session-to-session history type change constraints: - /// - /// If there is no top array at the beginning of a new session, then all - /// history types (as returned by get_history_type()) are possible during - /// that session. Otherwise there must have been a preceding session (at - /// least one that adds the top array), and the following rules then apply: - /// - ///
-    ///
-    ///                      Type stored in
-    ///   Type used during   Realm file at
-    ///   preceding          beginning of     Possible history types (as returned by
-    ///   session            new session      get_history_type()) during new session
-    ///   ----------------------------------------------------------------------------
-    ///   hist_None          hist_None        hist_None, hist_OutOfRealm, hist_InRealm
-    ///   hist_OutOfRealm    hist_None        hist_None, hist_OutOfRealm, hist_InRealm
-    ///   hist_InRealm       hist_InRealm     hist_InRealm
-    ///   hist_Sync          hist_Sync        hist_Sync
-    ///
-    /// 
- /// - /// This function must return \ref hist_None when, and only when - /// get_history() returns null. - virtual HistoryType get_history_type() const noexcept = 0; - - /// Returns an object that gives access to the history of changesets in a - /// way that allows for continuous transactions to work - /// (Group::advance_transact() in particular). - /// - /// This function must return null when, and only when get_history_type() - /// returns \ref hist_None. - virtual _impl::History* get_history() = 0; - - /// Returns false by default, but must return true if, and only if this - /// history object represents a session participant that is a sync - /// agent. This is used to enforce the "maximum one sync agent per session" - /// constraint. - virtual bool is_sync_agent() const noexcept; - - virtual ~Replication() noexcept - { - } - -protected: - Replication(); - - - //@{ - - /// do_initiate_transact() is called by initiate_transact(), and likewise - /// for do_prepare_commit), do_finalize_commit(), and do_abort_transact(). - /// - /// With respect to exception safety, the Replication implementation has two - /// options: It can prepare to accept the accumulated changeset in - /// do_prepapre_commit() by allocating all required resources, and delay the - /// actual acceptance to do_finalize_commit(), which requires that the final - /// acceptance can be done without any risk of failure. Alternatively, the - /// Replication implementation can fully accept the changeset in - /// do_prepapre_commit() (allowing for failure), and then discard that - /// changeset during the next invocation of do_initiate_transact() if - /// `current_version` indicates that the previous transaction failed. - - virtual void do_initiate_transact(version_type current_version, bool history_updated) = 0; - virtual version_type do_prepare_commit(version_type orig_version) = 0; - virtual void do_finalize_commit() noexcept = 0; - virtual void do_abort_transact() noexcept = 0; - - //@} - - - virtual void do_interrupt() noexcept = 0; - - virtual void do_clear_interrupt() noexcept = 0; - - friend class _impl::TransactReverser; -}; - - -class Replication::Interrupted : public std::exception { -public: - const char* what() const noexcept override - { - return "Interrupted"; - } -}; - - -class TrivialReplication : public Replication { -public: - ~TrivialReplication() noexcept - { - } - -protected: - typedef Replication::version_type version_type; - - TrivialReplication(const std::string& database_file); - - virtual version_type prepare_changeset(const char* data, size_t size, version_type orig_version) = 0; - virtual void finalize_changeset() noexcept = 0; - - static void apply_changeset(const char* data, size_t size, SharedGroup& target, util::Logger* logger = nullptr); - - bool is_history_updated() const noexcept; - - BinaryData get_uncommitted_changes() const noexcept; - - std::string get_database_path() override; - void initialize(SharedGroup&) override; - void do_initiate_transact(version_type, bool) override; - version_type do_prepare_commit(version_type orig_version) override; - void do_finalize_commit() noexcept override; - void do_abort_transact() noexcept override; - void do_interrupt() noexcept override; - void do_clear_interrupt() noexcept override; - void transact_log_reserve(size_t n, char** new_begin, char** new_end) override; - void transact_log_append(const char* data, size_t size, char** new_begin, char** new_end) override; - -private: - const std::string m_database_file; - util::Buffer m_transact_log_buffer; - bool m_history_updated; - void internal_transact_log_reserve(size_t, char** new_begin, char** new_end); - - size_t transact_log_size(); -}; - - -// Implementation: - -inline Replication::Replication() - : _impl::TransactLogConvenientEncoder(static_cast<_impl::TransactLogStream&>(*this)) -{ -} - -inline void Replication::initiate_transact(version_type current_version, bool history_updated) -{ - do_initiate_transact(current_version, history_updated); - reset_selection_caches(); -} - -inline Replication::version_type Replication::prepare_commit(version_type orig_version) -{ - return do_prepare_commit(orig_version); -} - -inline void Replication::finalize_commit() noexcept -{ - do_finalize_commit(); -} - -inline void Replication::abort_transact() noexcept -{ - do_abort_transact(); -} - -inline void Replication::interrupt() noexcept -{ - do_interrupt(); -} - -inline void Replication::clear_interrupt() noexcept -{ - do_clear_interrupt(); -} - -inline bool Replication::is_sync_agent() const noexcept -{ - return false; -} - -inline TrivialReplication::TrivialReplication(const std::string& database_file) - : m_database_file(database_file) -{ -} - -inline bool TrivialReplication::is_history_updated() const noexcept -{ - return m_history_updated; -} - -inline BinaryData TrivialReplication::get_uncommitted_changes() const noexcept -{ - const char* data = m_transact_log_buffer.data(); - size_t size = write_position() - data; - return BinaryData(data, size); -} - -inline size_t TrivialReplication::transact_log_size() -{ - return write_position() - m_transact_log_buffer.data(); -} - -inline void TrivialReplication::transact_log_reserve(size_t n, char** new_begin, char** new_end) -{ - internal_transact_log_reserve(n, new_begin, new_end); -} - -inline void TrivialReplication::internal_transact_log_reserve(size_t n, char** new_begin, char** new_end) -{ - char* data = m_transact_log_buffer.data(); - size_t size = write_position() - data; - m_transact_log_buffer.reserve_extra(size, n); - data = m_transact_log_buffer.data(); // May have changed - *new_begin = data + size; - *new_end = data + m_transact_log_buffer.size(); -} - -} // namespace realm - -#endif // REALM_REPLICATION_HPP diff --git a/Example/Pods/Realm/include/core/realm/row.hpp b/Example/Pods/Realm/include/core/realm/row.hpp deleted file mode 100644 index f79794b..0000000 --- a/Example/Pods/Realm/include/core/realm/row.hpp +++ /dev/null @@ -1,818 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_ROW_HPP -#define REALM_ROW_HPP - -#include - -#include -#include -#include -#include -#include - -namespace realm { - -template -class BasicRow; - - -/// This class is a "mixin" and contains the common set of functions for several -/// distinct row-like classes. -/// -/// There is a direct and natural correspondance between the functions in this -/// class and functions in Table of the same name. For example: -/// -/// table[i].get_int(j) == table.get_int(i,j) -/// -/// The effect of calling most of the row accessor functions on a detached -/// accessor is unspecified and may lead to general corruption, and/or a -/// crash. The exceptions are is_attached(), detach(), get_table(), get_index(), -/// and the destructor. Note however, that get_index() will still return an -/// unspecified value for a deatched accessor. -/// -/// When a row accessor is evaluated in a boolean context, it evaluates to true -/// if, and only if it is attached. -/// -/// \tparam T A const or non-const table type (currently either `Table` or -/// `const Table`). -/// -/// \tparam R A specific row accessor class (BasicRow or BasicRowExpr) providing -/// members `T* impl_get_table() const`, `size_t impl_get_row_ndx() -/// const`, and `void impl_detach()`. Neither are allowed to throw. -/// -/// \sa Table -/// \sa BasicRow -template -class RowFuncs { -public: - typedef T table_type; - - typedef BasicTableRef ConstTableRef; - typedef BasicTableRef TableRef; // Same as ConstTableRef if `T` is 'const' - - typedef typename util::CopyConst::type L; - using ConstLinkViewRef = std::shared_ptr; - using LinkViewRef = std::shared_ptr; // Same as ConstLinkViewRef if `T` is 'const' - - int_fast64_t get_int(size_t col_ndx) const noexcept; - bool get_bool(size_t col_ndx) const noexcept; - float get_float(size_t col_ndx) const noexcept; - double get_double(size_t col_ndx) const noexcept; - StringData get_string(size_t col_ndx) const noexcept; - BinaryData get_binary(size_t col_ndx) const noexcept; - OldDateTime get_olddatetime(size_t col_ndx) const noexcept; - Timestamp get_timestamp(size_t col_ndx) const noexcept; - ConstTableRef get_subtable(size_t col_ndx) const; - TableRef get_subtable(size_t col_ndx); - size_t get_subtable_size(size_t col_ndx) const noexcept; - size_t get_link(size_t col_ndx) const noexcept; - bool is_null_link(size_t col_ndx) const noexcept; - bool is_null(size_t col_ndx) const noexcept; - ConstLinkViewRef get_linklist(size_t col_ndx) const; - LinkViewRef get_linklist(size_t col_ndx); - bool linklist_is_empty(size_t col_ndx) const noexcept; - size_t get_link_count(size_t col_ndx) const noexcept; - Mixed get_mixed(size_t col_ndx) const noexcept; - DataType get_mixed_type(size_t col_ndx) const noexcept; - template - U get(size_t col_ndx) const noexcept; - - void set_int(size_t col_ndx, int_fast64_t value); - void set_int_unique(size_t col_ndx, int_fast64_t value); - void set_bool(size_t col_ndx, bool value); - void set_float(size_t col_ndx, float value); - void set_double(size_t col_ndx, double value); - void set_string(size_t col_ndx, StringData value); - void set_string_unique(size_t col_ndx, StringData value); - void set_binary(size_t col_ndx, BinaryData value); - void set_olddatetime(size_t col_ndx, OldDateTime value); - void set_timestamp(size_t col_ndx, Timestamp value); - void set_subtable(size_t col_ndx, const Table* value); - void set_link(size_t col_ndx, size_t value); - void nullify_link(size_t col_ndx); - void set_mixed(size_t col_ndx, Mixed value); - void set_mixed_subtable(size_t col_ndx, const Table* value); - void set_null(size_t col_ndx); - void set_null_unique(size_t col_ndx); - - void insert_substring(size_t col_ndx, size_t pos, StringData); - void remove_substring(size_t col_ndx, size_t pos, size_t size); - - //@{ - /// Note that these operations will cause the row accessor to be detached. - void remove(); - void move_last_over(); - //@} - - size_t get_backlink_count(const Table& src_table, size_t src_col_ndx) const noexcept; - size_t get_backlink(const Table& src_table, size_t src_col_ndx, size_t backlink_ndx) const noexcept; - - size_t get_column_count() const noexcept; - DataType get_column_type(size_t col_ndx) const noexcept; - StringData get_column_name(size_t col_ndx) const noexcept; - size_t get_column_index(StringData name) const noexcept; - - /// Returns true if, and only if this accessor is currently attached to a - /// row. - /// - /// A row accesor may get detached from the underlying row for various - /// reasons (see below). When it does, it no longer refers to anything, and - /// can no longer be used, except for calling is_attached(), detach(), - /// get_table(), get_index(), and the destructor. The consequences of - /// calling other methods on a detached row accessor are unspecified. There - /// are a few Realm functions (Table::find_pkey_int()) that return a - /// detached row accessor to indicate a 'null' result. In all other cases, - /// however, row accessors obtained by calling functions in the Realm API - /// are always in the 'attached' state immediately upon return from those - /// functions. - /// - /// A row accessor becomes detached if the underlying row is removed, if the - /// associated table accessor becomes detached, or if the detach() method is - /// called. A row accessor does not become detached for any other reason. - bool is_attached() const noexcept; - - /// Detach this accessor from the row it was attached to. This function has - /// no effect if the accessor was already detached (idempotency). - void detach() noexcept; - - /// The table containing the row to which this accessor is currently - /// bound. For a detached accessor, the returned value is null. - const table_type* get_table() const noexcept; - table_type* get_table() noexcept; - - /// The index of the row to which this accessor is currently bound. For a - /// detached accessor, the returned value is unspecified. - size_t get_index() const noexcept; - - explicit operator bool() const noexcept; - -private: - const T* table() const noexcept; - T* table() noexcept; - size_t row_ndx() const noexcept; -}; - - -/// This class is a special kind of row accessor. It differes from a real row -/// accessor (BasicRow) by having a trivial and fast copy constructor and -/// descructor. It is supposed to be used as the return type of functions such -/// as Table::operator[](), and then to be used as a basis for constructing a -/// real row accessor. Objects of this class are intended to only ever exist as -/// temporaries. -/// -/// In contrast to a real row accessor (`BasicRow`), objects of this class do -/// not keep the parent table "alive", nor are they maintained (adjusted) across -/// row insertions and row removals like real row accessors are. -/// -/// \sa BasicRow -template -class BasicRowExpr : public RowFuncs> { -public: - BasicRowExpr() noexcept; - - template - BasicRowExpr(const BasicRowExpr&) noexcept; - -private: - T* m_table; // nullptr if detached. - size_t m_row_ndx; // Undefined if detached. - - BasicRowExpr(T*, size_t init_row_ndx) noexcept; - - T* impl_get_table() const noexcept; - size_t impl_get_row_ndx() const noexcept; - void impl_detach() noexcept; - - // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible - // from RowFuncs. - friend class RowFuncs>; - - // Make m_table and m_col_ndx accessible from BasicRowExpr(const - // BasicRowExpr&) for any U. - template - friend class BasicRowExpr; - - // Make m_table and m_col_ndx accessible from - // BasicRow::BaicRow(BasicRowExpr) for any U. - template - friend class BasicRow; - - // Make BasicRowExpr(T*, size_t) accessible from Table. - friend class Table; -}; - -// fwd decl -class Group; - -class RowBase { -protected: - TableRef m_table; // nullptr if detached. - size_t m_row_ndx; // Undefined if detached. - - void attach(Table*, size_t row_ndx) noexcept; - void reattach(Table*, size_t row_ndx) noexcept; - void impl_detach() noexcept; - - RowBase() - { - } - - RowBase(const RowBase&) = delete; - using HandoverPatch = RowBaseHandoverPatch; - - RowBase(const RowBase& source, HandoverPatch& patch); - -public: - static void generate_patch(const RowBase& source, HandoverPatch& patch); - void apply_patch(HandoverPatch& patch, Group& group); - -private: - RowBase* m_prev = nullptr; // nullptr if first, undefined if detached. - RowBase* m_next = nullptr; // nullptr if last, undefined if detached. - - // Table needs to be able to modify m_table and m_row_ndx. - friend class Table; -}; - - -/// An accessor class for table rows (a.k.a. a "row accessor"). -/// -/// For as long as it remains attached, a row accessor will keep the parent -/// table accessor alive. In case the lifetime of the parent table is not -/// managed by reference counting (such as when the table is an automatic -/// variable on the stack), the destruction of the table will cause all -/// remaining row accessors to be detached. -/// -/// While attached, a row accessor is bound to a particular row of the parent -/// table. If that row is removed, the accesssor becomes detached. If rows are -/// inserted or removed before it (at lower row index), then the accessor is -/// automatically adjusted to account for the change in index of the row to -/// which the accessor is bound. In other words, a row accessor is bound to the -/// contents of a row, not to a row index. See also is_attached(). -/// -/// Row accessors are created and used as follows: -/// -/// Row row = table[7]; // 8th row of `table` -/// ConstRow crow = ctable[2]; // 3rd row of const `ctable` -/// Row first_row = table.front(); -/// Row last_row = table.back(); -/// -/// float v = row.get_float(1); // Get the float in the 2nd column -/// row.set_string(0, "foo"); // Update the string in the 1st column -/// -/// Table* t = row.get_table(); // The parent table -/// size_t i = row.get_index(); // The current row index -/// -/// \sa RowFuncs -template -class BasicRow : private RowBase, public RowFuncs> { -public: - BasicRow() noexcept; - - template - BasicRow(BasicRowExpr) noexcept; - - BasicRow(const BasicRow&) noexcept; - - template - BasicRow(const BasicRow&) noexcept; - - template - BasicRow& operator=(BasicRowExpr) noexcept; - - template - BasicRow& operator=(BasicRow) noexcept; - - BasicRow& operator=(const BasicRow&) noexcept; - - ~BasicRow() noexcept; - -private: - T* impl_get_table() const noexcept; - size_t impl_get_row_ndx() const noexcept; - - // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible - // from RowFuncs. - friend class RowFuncs>; - - // Make m_table and m_col_ndx accessible from BasicRow(const BasicRow&) - // for any U. - template - friend class BasicRow; - -public: - std::unique_ptr> clone_for_handover(std::unique_ptr& patch) const - { - patch.reset(new HandoverPatch); - std::unique_ptr> retval(new BasicRow(*this, *patch)); - return retval; - } - - static void generate_patch(const BasicRow& row, std::unique_ptr& patch) - { - patch.reset(new HandoverPatch); - RowBase::generate_patch(row, *patch); - } - - void apply_and_consume_patch(std::unique_ptr& patch, Group& group) - { - apply_patch(*patch, group); - patch.reset(); - } - - void apply_patch(HandoverPatch& patch, Group& group) - { - RowBase::apply_patch(patch, group); - } - -private: - BasicRow(const BasicRow& source, HandoverPatch& patch) - : RowBase(source, patch) - { - } - friend class SharedGroup; -}; - -typedef BasicRow Row; -typedef BasicRow ConstRow; - - -// Implementation - -template -inline int_fast64_t RowFuncs::get_int(size_t col_ndx) const noexcept -{ - return table()->get_int(col_ndx, row_ndx()); -} - -template -inline bool RowFuncs::get_bool(size_t col_ndx) const noexcept -{ - return table()->get_bool(col_ndx, row_ndx()); -} - -template -inline float RowFuncs::get_float(size_t col_ndx) const noexcept -{ - return table()->get_float(col_ndx, row_ndx()); -} - -template -inline double RowFuncs::get_double(size_t col_ndx) const noexcept -{ - return table()->get_double(col_ndx, row_ndx()); -} - -template -inline StringData RowFuncs::get_string(size_t col_ndx) const noexcept -{ - return table()->get_string(col_ndx, row_ndx()); -} - -template -inline BinaryData RowFuncs::get_binary(size_t col_ndx) const noexcept -{ - return table()->get_binary(col_ndx, row_ndx()); -} - -template -inline OldDateTime RowFuncs::get_olddatetime(size_t col_ndx) const noexcept -{ - return table()->get_olddatetime(col_ndx, row_ndx()); -} - -template -inline Timestamp RowFuncs::get_timestamp(size_t col_ndx) const noexcept -{ - return table()->get_timestamp(col_ndx, row_ndx()); -} - -template -inline typename RowFuncs::ConstTableRef RowFuncs::get_subtable(size_t col_ndx) const -{ - return table()->get_subtable(col_ndx, row_ndx()); // Throws -} - -template -inline typename RowFuncs::TableRef RowFuncs::get_subtable(size_t col_ndx) -{ - return table()->get_subtable(col_ndx, row_ndx()); // Throws -} - -template -inline size_t RowFuncs::get_subtable_size(size_t col_ndx) const noexcept -{ - return table()->get_subtable_size(col_ndx, row_ndx()); -} - -template -inline size_t RowFuncs::get_link(size_t col_ndx) const noexcept -{ - return table()->get_link(col_ndx, row_ndx()); -} - -template -inline bool RowFuncs::is_null_link(size_t col_ndx) const noexcept -{ - return table()->is_null_link(col_ndx, row_ndx()); -} - -template -inline bool RowFuncs::is_null(size_t col_ndx) const noexcept -{ - return table()->is_null(col_ndx, row_ndx()); -} - -template -inline typename RowFuncs::ConstLinkViewRef RowFuncs::get_linklist(size_t col_ndx) const -{ - return table()->get_linklist(col_ndx, row_ndx()); // Throws -} - -template -inline typename RowFuncs::LinkViewRef RowFuncs::get_linklist(size_t col_ndx) -{ - return table()->get_linklist(col_ndx, row_ndx()); // Throws -} - -template -inline bool RowFuncs::linklist_is_empty(size_t col_ndx) const noexcept -{ - return table()->linklist_is_empty(col_ndx, row_ndx()); -} - -template -inline size_t RowFuncs::get_link_count(size_t col_ndx) const noexcept -{ - return table()->get_link_count(col_ndx, row_ndx()); -} - -template -inline Mixed RowFuncs::get_mixed(size_t col_ndx) const noexcept -{ - return table()->get_mixed(col_ndx, row_ndx()); -} - -template -inline DataType RowFuncs::get_mixed_type(size_t col_ndx) const noexcept -{ - return table()->get_mixed_type(col_ndx, row_ndx()); -} - -template -template -inline U RowFuncs::get(size_t col_ndx) const noexcept -{ - return table()->template get(col_ndx, row_ndx()); -} - -template -inline void RowFuncs::set_int(size_t col_ndx, int_fast64_t value) -{ - table()->set_int(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_int_unique(size_t col_ndx, int_fast64_t value) -{ - table()->set_int_unique(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_bool(size_t col_ndx, bool value) -{ - table()->set_bool(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_float(size_t col_ndx, float value) -{ - table()->set_float(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_double(size_t col_ndx, double value) -{ - table()->set_double(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_string(size_t col_ndx, StringData value) -{ - table()->set_string(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_string_unique(size_t col_ndx, StringData value) -{ - table()->set_string_unique(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_binary(size_t col_ndx, BinaryData value) -{ - table()->set_binary(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_olddatetime(size_t col_ndx, OldDateTime value) -{ - table()->set_olddatetime(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_timestamp(size_t col_ndx, Timestamp value) -{ - table()->set_timestamp(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_subtable(size_t col_ndx, const Table* value) -{ - table()->set_subtable(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_link(size_t col_ndx, size_t value) -{ - table()->set_link(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::nullify_link(size_t col_ndx) -{ - table()->nullify_link(col_ndx, row_ndx()); // Throws -} - -template -inline void RowFuncs::set_mixed(size_t col_ndx, Mixed value) -{ - table()->set_mixed(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_mixed_subtable(size_t col_ndx, const Table* value) -{ - table()->set_mixed_subtable(col_ndx, row_ndx(), value); // Throws -} - -template -inline void RowFuncs::set_null(size_t col_ndx) -{ - table()->set_null(col_ndx, row_ndx()); // Throws -} - -template -inline void RowFuncs::set_null_unique(size_t col_ndx) -{ - table()->set_null_unique(col_ndx, row_ndx()); // Throws -} - -template -inline void RowFuncs::insert_substring(size_t col_ndx, size_t pos, StringData value) -{ - table()->insert_substring(col_ndx, row_ndx(), pos, value); // Throws -} - -template -inline void RowFuncs::remove_substring(size_t col_ndx, size_t pos, size_t size) -{ - table()->remove_substring(col_ndx, row_ndx(), pos, size); // Throws -} - -template -inline void RowFuncs::remove() -{ - table()->remove(row_ndx()); // Throws -} - -template -inline void RowFuncs::move_last_over() -{ - table()->move_last_over(row_ndx()); // Throws -} - -template -inline size_t RowFuncs::get_backlink_count(const Table& src_table, size_t src_col_ndx) const noexcept -{ - return table()->get_backlink_count(row_ndx(), src_table, src_col_ndx); -} - -template -inline size_t RowFuncs::get_backlink(const Table& src_table, size_t src_col_ndx, size_t backlink_ndx) const - noexcept -{ - return table()->get_backlink(row_ndx(), src_table, src_col_ndx, backlink_ndx); -} - -template -inline size_t RowFuncs::get_column_count() const noexcept -{ - return table()->get_column_count(); -} - -template -inline DataType RowFuncs::get_column_type(size_t col_ndx) const noexcept -{ - return table()->get_column_type(col_ndx); -} - -template -inline StringData RowFuncs::get_column_name(size_t col_ndx) const noexcept -{ - return table()->get_column_name(col_ndx); -} - -template -inline size_t RowFuncs::get_column_index(StringData name) const noexcept -{ - return table()->get_column_index(name); -} - -template -inline bool RowFuncs::is_attached() const noexcept -{ - return static_cast(this)->impl_get_table(); -} - -template -inline void RowFuncs::detach() noexcept -{ - static_cast(this)->impl_detach(); -} - -template -inline const T* RowFuncs::get_table() const noexcept -{ - return table(); -} - -template -inline T* RowFuncs::get_table() noexcept -{ - return table(); -} - -template -inline size_t RowFuncs::get_index() const noexcept -{ - return row_ndx(); -} - -template -inline RowFuncs::operator bool() const noexcept -{ - return is_attached(); -} - -template -inline const T* RowFuncs::table() const noexcept -{ - return static_cast(this)->impl_get_table(); -} - -template -inline T* RowFuncs::table() noexcept -{ - return static_cast(this)->impl_get_table(); -} - -template -inline size_t RowFuncs::row_ndx() const noexcept -{ - return static_cast(this)->impl_get_row_ndx(); -} - - -template -inline BasicRowExpr::BasicRowExpr() noexcept - : m_table(0) - , m_row_ndx(0) -{ -} - -template -template -inline BasicRowExpr::BasicRowExpr(const BasicRowExpr& expr) noexcept - : m_table(expr.m_table) - , m_row_ndx(expr.m_row_ndx) -{ -} - -template -inline BasicRowExpr::BasicRowExpr(T* init_table, size_t init_row_ndx) noexcept - : m_table(init_table) - , m_row_ndx(init_row_ndx) -{ -} - -template -inline T* BasicRowExpr::impl_get_table() const noexcept -{ - return m_table; -} - -template -inline size_t BasicRowExpr::impl_get_row_ndx() const noexcept -{ - return m_row_ndx; -} - -template -inline void BasicRowExpr::impl_detach() noexcept -{ - m_table = nullptr; -} - - -template -inline BasicRow::BasicRow() noexcept -{ -} - -template -inline BasicRow::BasicRow(const BasicRow& row) noexcept - : RowBase() -{ - attach(const_cast(row.m_table.get()), row.m_row_ndx); -} - -template -template -inline BasicRow::BasicRow(BasicRowExpr expr) noexcept -{ - T* expr_table = expr.m_table; // Check that pointer types are compatible - attach(const_cast(expr_table), expr.m_row_ndx); -} - -template -template -inline BasicRow::BasicRow(const BasicRow& row) noexcept -{ - T* row_table = row.m_table.get(); // Check that pointer types are compatible - attach(const_cast(row_table), row.m_row_ndx); -} - -template -template -inline BasicRow& BasicRow::operator=(BasicRowExpr expr) noexcept -{ - T* expr_table = expr.m_table; // Check that pointer types are compatible - reattach(const_cast(expr_table), expr.m_row_ndx); - return *this; -} - -template -template -inline BasicRow& BasicRow::operator=(BasicRow row) noexcept -{ - T* row_table = row.m_table.get(); // Check that pointer types are compatible - reattach(const_cast(row_table), row.m_row_ndx); - return *this; -} - -template -inline BasicRow& BasicRow::operator=(const BasicRow& row) noexcept -{ - reattach(const_cast(row.m_table.get()), row.m_row_ndx); - return *this; -} - -template -inline BasicRow::~BasicRow() noexcept -{ - RowBase::impl_detach(); -} - -template -inline T* BasicRow::impl_get_table() const noexcept -{ - return m_table.get(); -} - -template -inline size_t BasicRow::impl_get_row_ndx() const noexcept -{ - return m_row_ndx; -} - -} // namespace realm - -#endif // REALM_ROW_HPP diff --git a/Example/Pods/Realm/include/core/realm/spec.hpp b/Example/Pods/Realm/include/core/realm/spec.hpp deleted file mode 100644 index 78448c9..0000000 --- a/Example/Pods/Realm/include/core/realm/spec.hpp +++ /dev/null @@ -1,476 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_SPEC_HPP -#define REALM_SPEC_HPP - -#include -#include -#include -#include -#include -#include - -namespace realm { - -class Table; -class SubspecRef; -class ConstSubspecRef; - -class Spec { -public: - Spec(SubspecRef) noexcept; - ~Spec() noexcept; - - Allocator& get_alloc() const noexcept; - - bool has_strong_link_columns() noexcept; - - void insert_column(size_t column_ndx, ColumnType type, StringData name, ColumnAttr attr = col_attr_None); - void rename_column(size_t column_ndx, StringData new_name); - void move_column(size_t from, size_t to); - - /// Erase the column at the specified index, and move columns at - /// succeeding indexes to the next lower index. - /// - /// This function is guaranteed to *never* throw if the spec is - /// used in a non-transactional context, or if the spec has - /// already been successfully modified within the current write - /// transaction. - void erase_column(size_t column_ndx); - - //@{ - // If a new Spec is constructed from the returned subspec - // reference, it is the responsibility of the application that the - // parent Spec object (this) is kept alive for at least as long as - // the new Spec object. - SubspecRef get_subtable_spec(size_t column_ndx) noexcept; - ConstSubspecRef get_subtable_spec(size_t column_ndx) const noexcept; - //@} - - // Column info - size_t get_column_count() const noexcept; - size_t get_public_column_count() const noexcept; - DataType get_public_column_type(size_t column_ndx) const noexcept; - ColumnType get_column_type(size_t column_ndx) const noexcept; - StringData get_column_name(size_t column_ndx) const noexcept; - - /// Returns size_t(-1) if the specified column is not found. - size_t get_column_index(StringData name) const noexcept; - - // Column Attributes - ColumnAttr get_column_attr(size_t column_ndx) const noexcept; - - size_t get_subspec_ndx(size_t column_ndx) const noexcept; - ref_type get_subspec_ref(size_t subspec_ndx) const noexcept; - SubspecRef get_subspec_by_ndx(size_t subspec_ndx) noexcept; - ConstSubspecRef get_subspec_by_ndx(size_t subspec_ndx) const noexcept; - - // Auto Enumerated string columns - void upgrade_string_to_enum(size_t column_ndx, ref_type keys_ref, ArrayParent*& keys_parent, size_t& keys_ndx); - size_t get_enumkeys_ndx(size_t column_ndx) const noexcept; - ref_type get_enumkeys_ref(size_t column_ndx, ArrayParent** keys_parent = nullptr, - size_t* keys_ndx = nullptr) noexcept; - - // Links - size_t get_opposite_link_table_ndx(size_t column_ndx) const noexcept; - void set_opposite_link_table_ndx(size_t column_ndx, size_t table_ndx); - bool has_backlinks() const noexcept; - void set_backlink_origin_column(size_t backlink_col_ndx, size_t origin_col_ndx); - size_t get_origin_column_ndx(size_t backlink_col_ndx) const noexcept; - size_t find_backlink_column(size_t origin_table_ndx, size_t origin_col_ndx) const noexcept; - - /// Get position in `Table::m_columns` of the specified column. It may be - /// different from the specified logical column index due to the presence of - /// search indexes, since their top refs are stored in Table::m_columns as - /// well. - size_t get_column_ndx_in_parent(size_t column_ndx) const; - - //@{ - /// Compare two table specs for equality. - bool operator==(const Spec&) const noexcept; - bool operator!=(const Spec&) const noexcept; - //@} - - void destroy() noexcept; - - size_t get_ndx_in_parent() const noexcept; - void set_ndx_in_parent(size_t) noexcept; - -#ifdef REALM_DEBUG - void verify() const; - void to_dot(std::ostream&, StringData title = StringData()) const; -#endif - -private: - // Underlying array structure. - // - // `m_subspecs` contains one entry for each subtable column, one entry for - // each link or link list columns, two entries for each backlink column, and - // zero entries for all other column types. For subtable columns the entry - // is a ref pointing to the subtable spec, for link and link list columns it - // is the group-level table index of the target table, and for backlink - // columns the first entry is the group-level table index of the origin - // table, and the second entry is the index of the origin column in the - // origin table. - Array m_top; - ArrayInteger m_types; // 1st slot in m_top - ArrayString m_names; // 2nd slot in m_top - ArrayInteger m_attr; // 3rd slot in m_top - Array m_subspecs; // 4th slot in m_top (optional) - Array m_enumkeys; // 5th slot in m_top (optional) - bool m_has_strong_link_columns; - - Spec(Allocator&) noexcept; // Unattached - - void init(ref_type) noexcept; - void init(MemRef) noexcept; - void init(SubspecRef) noexcept; - void update_has_strong_link_columns() noexcept; - - // Similar in function to Array::init_from_parent(). - void init_from_parent() noexcept; - - ref_type get_ref() const noexcept; - - /// Called in the context of Group::commit() to ensure that - /// attached table accessors stay valid across a commit. Please - /// note that this works only for non-transactional commits. Table - /// accessors obtained during a transaction are always detached - /// when the transaction ends. - void update_from_parent(size_t old_baseline) noexcept; - - void set_parent(ArrayParent*, size_t ndx_in_parent) noexcept; - - void set_column_type(size_t column_ndx, ColumnType type); - void set_column_attr(size_t column_ndx, ColumnAttr attr); - - /// Construct an empty spec and return just the reference to the - /// underlying memory. - static MemRef create_empty_spec(Allocator&); - - struct ColumnInfo { - size_t m_column_ref_ndx = 0; ///< Index within Table::m_columns - bool m_has_search_index = false; - }; - - ColumnInfo get_column_info(size_t column_ndx) const noexcept; - - size_t get_subspec_ndx_after(size_t column_ndx, size_t skip_column_ndx) const noexcept; - size_t get_subspec_entries_for_col_type(ColumnType type) const noexcept; - bool has_subspec() const noexcept; - - // Returns false if the spec has no columns, otherwise it returns - // true and sets `type` to the type of the first column. - static bool get_first_column_type_from_ref(ref_type, Allocator&, ColumnType& type) noexcept; - - friend class Replication; - friend class Group; - friend class Table; -}; - - -class SubspecRef { -public: - struct const_cast_tag { - }; - SubspecRef(const_cast_tag, ConstSubspecRef r) noexcept; - ~SubspecRef() noexcept - { - } - Allocator& get_alloc() const noexcept - { - return m_parent->get_alloc(); - } - -private: - Array* const m_parent; - size_t const m_ndx_in_parent; - - SubspecRef(Array* parent, size_t ndx_in_parent) noexcept; - - friend class Spec; - friend class ConstSubspecRef; -}; - -class ConstSubspecRef { -public: - ConstSubspecRef(SubspecRef r) noexcept; - ~ConstSubspecRef() noexcept - { - } - Allocator& get_alloc() const noexcept - { - return m_parent->get_alloc(); - } - -private: - const Array* const m_parent; - size_t const m_ndx_in_parent; - - ConstSubspecRef(const Array* parent, size_t ndx_in_parent) noexcept; - - friend class Spec; - friend class SubspecRef; -}; - - -// Implementation: - -inline Allocator& Spec::get_alloc() const noexcept -{ - return m_top.get_alloc(); -} - -inline bool Spec::has_strong_link_columns() noexcept -{ - return m_has_strong_link_columns; -} - -inline ref_type Spec::get_subspec_ref(size_t subspec_ndx) const noexcept -{ - REALM_ASSERT(subspec_ndx < m_subspecs.size()); - - // Note that this addresses subspecs directly, indexing - // by number of sub-table columns - return m_subspecs.get_as_ref(subspec_ndx); -} - -inline Spec::Spec(SubspecRef r) noexcept - : m_top(r.m_parent->get_alloc()) - , m_types(r.m_parent->get_alloc()) - , m_names(r.m_parent->get_alloc()) - , m_attr(r.m_parent->get_alloc()) - , m_subspecs(r.m_parent->get_alloc()) - , m_enumkeys(r.m_parent->get_alloc()) -{ - init(r); -} - -// Uninitialized Spec (call init() to init) -inline Spec::Spec(Allocator& alloc) noexcept - : m_top(alloc) - , m_types(alloc) - , m_names(alloc) - , m_attr(alloc) - , m_subspecs(alloc) - , m_enumkeys(alloc) -{ -} - -inline SubspecRef Spec::get_subtable_spec(size_t column_ndx) noexcept -{ - REALM_ASSERT(column_ndx < get_column_count()); - REALM_ASSERT(get_column_type(column_ndx) == col_type_Table); - size_t subspec_ndx = get_subspec_ndx(column_ndx); - return SubspecRef(&m_subspecs, subspec_ndx); -} - -inline ConstSubspecRef Spec::get_subtable_spec(size_t column_ndx) const noexcept -{ - REALM_ASSERT(column_ndx < get_column_count()); - REALM_ASSERT(get_column_type(column_ndx) == col_type_Table); - size_t subspec_ndx = get_subspec_ndx(column_ndx); - return ConstSubspecRef(&m_subspecs, subspec_ndx); -} - -inline SubspecRef Spec::get_subspec_by_ndx(size_t subspec_ndx) noexcept -{ - return SubspecRef(&m_subspecs, subspec_ndx); -} - -inline ConstSubspecRef Spec::get_subspec_by_ndx(size_t subspec_ndx) const noexcept -{ - return const_cast(this)->get_subspec_by_ndx(subspec_ndx); -} - -inline void Spec::init(ref_type ref) noexcept -{ - MemRef mem(ref, get_alloc()); - init(mem); -} - -inline void Spec::init(SubspecRef r) noexcept -{ - m_top.set_parent(r.m_parent, r.m_ndx_in_parent); - ref_type ref = r.m_parent->get_as_ref(r.m_ndx_in_parent); - init(ref); -} - -inline void Spec::init_from_parent() noexcept -{ - ref_type ref = m_top.get_ref_from_parent(); - init(ref); -} - -inline void Spec::destroy() noexcept -{ - m_top.destroy_deep(); -} - -inline size_t Spec::get_ndx_in_parent() const noexcept -{ - return m_top.get_ndx_in_parent(); -} - -inline void Spec::set_ndx_in_parent(size_t ndx) noexcept -{ - m_top.set_ndx_in_parent(ndx); -} - -inline ref_type Spec::get_ref() const noexcept -{ - return m_top.get_ref(); -} - -inline void Spec::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept -{ - m_top.set_parent(parent, ndx_in_parent); -} - -inline void Spec::rename_column(size_t column_ndx, StringData new_name) -{ - REALM_ASSERT(column_ndx < m_types.size()); - m_names.set(column_ndx, new_name); -} - -inline size_t Spec::get_column_count() const noexcept -{ - // This is the total count of columns, including backlinks (not public) - return m_types.size(); -} - -inline size_t Spec::get_public_column_count() const noexcept -{ - // Backlinks are the last columns, and do not have names, so getting - // the number of names gives us the count of user facing columns - return m_names.size(); -} - -inline ColumnType Spec::get_column_type(size_t ndx) const noexcept -{ - REALM_ASSERT(ndx < get_column_count()); - return ColumnType(m_types.get(ndx)); -} - -inline void Spec::set_column_type(size_t column_ndx, ColumnType type) -{ - REALM_ASSERT(column_ndx < get_column_count()); - - // At this point we only support upgrading to string enum - REALM_ASSERT(ColumnType(m_types.get(column_ndx)) == col_type_String); - REALM_ASSERT(type == col_type_StringEnum); - - m_types.set(column_ndx, type); // Throws - - update_has_strong_link_columns(); -} - -inline ColumnAttr Spec::get_column_attr(size_t ndx) const noexcept -{ - REALM_ASSERT(ndx < get_column_count()); - return ColumnAttr(m_attr.get(ndx)); -} - -inline void Spec::set_column_attr(size_t column_ndx, ColumnAttr attr) -{ - REALM_ASSERT(column_ndx < get_column_count()); - - // At this point we only allow one attr at a time - // so setting it will overwrite existing. In the future - // we will allow combinations. - m_attr.set(column_ndx, attr); - - update_has_strong_link_columns(); -} - -inline StringData Spec::get_column_name(size_t ndx) const noexcept -{ - REALM_ASSERT(ndx < get_column_count()); - return m_names.get(ndx); -} - -inline size_t Spec::get_column_index(StringData name) const noexcept -{ - return m_names.find_first(name); -} - -inline bool Spec::get_first_column_type_from_ref(ref_type top_ref, Allocator& alloc, ColumnType& type) noexcept -{ - const char* top_header = alloc.translate(top_ref); - ref_type types_ref = to_ref(Array::get(top_header, 0)); - const char* types_header = alloc.translate(types_ref); - if (Array::get_size_from_header(types_header) == 0) - return false; - type = ColumnType(Array::get(types_header, 0)); - return true; -} - -inline bool Spec::has_backlinks() const noexcept -{ - // backlinks are always last and do not have names. - return m_names.size() < m_types.size(); - - // Fixme: It's bad design that backlinks are stored and recognized like this. Backlink columns - // should be a column type like any other, and we should find another way to hide them away from - // the user. -} - -// Spec will have a subspec when it contains a column which is one of: -// link, linklist, backlink, or subtable. It is possible for m_top.size() -// to contain an entry for m_subspecs (at index 3) but this reference -// may be empty if the spec contains enumkeys (at index 4) but no subspec types. -inline bool Spec::has_subspec() const noexcept -{ - return (m_top.size() >= 4) && (m_top.get_as_ref(3) != 0); -} - -inline bool Spec::operator!=(const Spec& s) const noexcept -{ - return !(*this == s); -} - - -inline SubspecRef::SubspecRef(Array* parent, size_t ndx_in_parent) noexcept - : m_parent(parent) - , m_ndx_in_parent(ndx_in_parent) -{ -} - -inline SubspecRef::SubspecRef(const_cast_tag, ConstSubspecRef r) noexcept - : m_parent(const_cast(r.m_parent)) - , m_ndx_in_parent(r.m_ndx_in_parent) -{ -} - -inline ConstSubspecRef::ConstSubspecRef(const Array* parent, size_t ndx_in_parent) noexcept - : m_parent(parent) - , m_ndx_in_parent(ndx_in_parent) -{ -} - -inline ConstSubspecRef::ConstSubspecRef(SubspecRef r) noexcept - : m_parent(r.m_parent) - , m_ndx_in_parent(r.m_ndx_in_parent) -{ -} - - -} // namespace realm - -#endif // REALM_SPEC_HPP diff --git a/Example/Pods/Realm/include/core/realm/string_data.hpp b/Example/Pods/Realm/include/core/realm/string_data.hpp deleted file mode 100644 index 14230cc..0000000 --- a/Example/Pods/Realm/include/core/realm/string_data.hpp +++ /dev/null @@ -1,407 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_STRING_HPP -#define REALM_STRING_HPP - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -namespace realm { - -/// A reference to a chunk of character data. -/// -/// An instance of this class can be thought of as a type tag on a region of -/// memory. It does not own the referenced memory, nor does it in any other way -/// attempt to manage the lifetime of it. -/// -/// A null character inside the referenced region is considered a part of the -/// string by Realm. -/// -/// For compatibility with C-style strings, when a string is stored in a Realm -/// database, it is always followed by a terminating null character, regardless -/// of whether the string itself has internal null characters. This means that -/// when a StringData object is extracted from Realm, the referenced region is -/// guaranteed to be followed immediately by an extra null character, but that -/// null character is not inside the referenced region. Therefore, all of the -/// following forms are guaranteed to return a pointer to a null-terminated -/// string: -/// -/// \code{.cpp} -/// -/// group.get_table_name(...).data() -/// table.get_column_name().data() -/// table.get_string(...).data() -/// table.get_mixed(...).get_string().data() -/// -/// \endcode -/// -/// Note that in general, no assumptions can be made about what follows a string -/// that is referenced by a StringData object, or whether anything follows it at -/// all. In particular, the receiver of a StringData object cannot assume that -/// the referenced string is followed by a null character unless there is an -/// externally provided guarantee. -/// -/// This class makes it possible to distinguish between a 'null' reference and a -/// reference to the empty string (see is_null()). -/// -/// \sa BinaryData -/// \sa Mixed -class StringData { -public: - /// Construct a null reference. - StringData() noexcept; - - /// If \a external_data is 'null', \a data_size must be zero. - StringData(const char* external_data, size_t data_size) noexcept; - - template - StringData(const std::basic_string&); - - template - operator std::basic_string() const; - - // StringData does not store data, callers must manage their own strings. - template - StringData(std::basic_string&&) = delete; - - template - StringData(const util::Optional>&); - - StringData(const null&) noexcept; - - /// Initialize from a zero terminated C style string. Pass null to construct - /// a null reference. - StringData(const char* c_str) noexcept; - - char operator[](size_t i) const noexcept; - - const char* data() const noexcept; - size_t size() const noexcept; - - /// Is this a null reference? - /// - /// An instance of StringData is a null reference when, and only when the - /// stored size is zero (size()) and the stored pointer is the null pointer - /// (data()). - /// - /// In the case of the empty string, the stored size is still zero, but the - /// stored pointer is **not** the null pointer. It could for example point - /// to the empty string literal. Note that the actual value of the pointer - /// is immaterial in this case (as long as it is not zero), because when the - /// size is zero, it is an error to dereference the pointer. - /// - /// Conversion of a StringData object to `bool` yields the logical negation - /// of the result of calling this function. In other words, a StringData - /// object is converted to true if it is not the null reference, otherwise - /// it is converted to false. - bool is_null() const noexcept; - - friend bool operator==(const StringData&, const StringData&) noexcept; - friend bool operator!=(const StringData&, const StringData&) noexcept; - - //@{ - /// Trivial bytewise lexicographical comparison. - friend bool operator<(const StringData&, const StringData&) noexcept; - friend bool operator>(const StringData&, const StringData&) noexcept; - friend bool operator<=(const StringData&, const StringData&) noexcept; - friend bool operator>=(const StringData&, const StringData&) noexcept; - //@} - - bool begins_with(StringData) const noexcept; - bool ends_with(StringData) const noexcept; - bool contains(StringData) const noexcept; - - // Wildcard matching ('?' for single char, '*' for zero or more chars) - // case insensitive version in unicode.hpp - bool like(StringData) const noexcept; - - //@{ - /// Undefined behavior if \a n, \a i, or i+n is greater than - /// size(). - StringData prefix(size_t n) const noexcept; - StringData suffix(size_t n) const noexcept; - StringData substr(size_t i, size_t n) const noexcept; - StringData substr(size_t i) const noexcept; - //@} - - template - friend std::basic_ostream& operator<<(std::basic_ostream&, const StringData&); - - explicit operator bool() const noexcept; - -private: - const char* m_data; - size_t m_size; - - static bool matchlike(const StringData& text, const StringData& pattern) noexcept; -}; - - -// Implementation: - -inline StringData::StringData() noexcept - : m_data(nullptr) - , m_size(0) -{ -} - -inline StringData::StringData(const char* external_data, size_t data_size) noexcept - : m_data(external_data) - , m_size(data_size) -{ - REALM_ASSERT_DEBUG(external_data || data_size == 0); -} - -template -inline StringData::StringData(const std::basic_string& s) - : m_data(s.data()) - , m_size(s.size()) -{ -} - -template -inline StringData::operator std::basic_string() const -{ - return std::basic_string(m_data, m_size); -} - -template -inline StringData::StringData(const util::Optional>& s) - : m_data(s ? s->data() : nullptr) - , m_size(s ? s->size() : 0) -{ -} - -inline StringData::StringData(const null&) noexcept - : m_data(nullptr) - , m_size(0) -{ -} - -inline StringData::StringData(const char* c_str) noexcept - : m_data(c_str) - , m_size(0) -{ - if (c_str) - m_size = std::char_traits::length(c_str); -} - -inline char StringData::operator[](size_t i) const noexcept -{ - return m_data[i]; -} - -inline const char* StringData::data() const noexcept -{ - return m_data; -} - -inline size_t StringData::size() const noexcept -{ - return m_size; -} - -inline bool StringData::is_null() const noexcept -{ - return !m_data; -} - -inline bool operator==(const StringData& a, const StringData& b) noexcept -{ - return a.m_size == b.m_size && a.is_null() == b.is_null() && safe_equal(a.m_data, a.m_data + a.m_size, b.m_data); -} - -inline bool operator!=(const StringData& a, const StringData& b) noexcept -{ - return !(a == b); -} - -inline bool operator<(const StringData& a, const StringData& b) noexcept -{ - if (a.is_null() && !b.is_null()) { - // Null strings are smaller than all other strings, and not - // equal to empty strings. - return true; - } - return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, b.m_data, b.m_data + b.m_size); -} - -inline bool operator>(const StringData& a, const StringData& b) noexcept -{ - return b < a; -} - -inline bool operator<=(const StringData& a, const StringData& b) noexcept -{ - return !(b < a); -} - -inline bool operator>=(const StringData& a, const StringData& b) noexcept -{ - return !(a < b); -} - -inline bool StringData::begins_with(StringData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - return d.m_size <= m_size && safe_equal(m_data, m_data + d.m_size, d.m_data); -} - -inline bool StringData::ends_with(StringData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - return d.m_size <= m_size && safe_equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data); -} - -inline bool StringData::contains(StringData d) const noexcept -{ - if (is_null() && !d.is_null()) - return false; - - return d.m_size == 0 || std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size; -} - -inline bool StringData::matchlike(const StringData& text, const StringData& pattern) noexcept -{ - std::vector textpos; - std::vector patternpos; - size_t p1 = 0; // position in text (haystack) - size_t p2 = 0; // position in pattern (needle) - - while (true) { - if (p1 == text.size()) { - if (p2 == pattern.size()) - return true; - if (p2 == pattern.size()-1 && pattern[p2] == '*') - return true; - goto no_match; - } - if (p2 == pattern.size()) - goto no_match; - - if (pattern[p2] == '*') { - textpos.push_back(p1); - patternpos.push_back(++p2); - continue; - } - if (pattern[p2] == '?') { - // utf-8 encoded characters may take up multiple bytes - if ((text[p1] & 0x80) == 0) { - ++p1; - ++p2; - continue; - } - else { - size_t p = 1; - while (p1+p != text.size() && (text[p1+p] & 0xc0) == 0x80) - ++p; - p1 += p; - ++p2; - continue; - } - } - - if (pattern[p2] == text[p1]) { - ++p1; - ++p2; - continue; - } - - no_match: - if (textpos.empty()) - return false; - else { - if (p1 == text.size()) { - textpos.pop_back(); - patternpos.pop_back(); - - if (textpos.empty()) - return false; - - p1 = textpos.back(); - } - else { - p1 = textpos.back(); - textpos.back() = ++p1; - } - p2 = patternpos.back(); - } - } -} - -inline bool StringData::like(StringData d) const noexcept -{ - if (is_null() || d.is_null()) { - return (is_null() && d.is_null()); - } - - return matchlike(*this, d); -} - -inline StringData StringData::prefix(size_t n) const noexcept -{ - return substr(0, n); -} - -inline StringData StringData::suffix(size_t n) const noexcept -{ - return substr(m_size - n); -} - -inline StringData StringData::substr(size_t i, size_t n) const noexcept -{ - return StringData(m_data + i, n); -} - -inline StringData StringData::substr(size_t i) const noexcept -{ - return substr(i, m_size - i); -} - -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const StringData& d) -{ - for (const char* i = d.m_data; i != d.m_data + d.m_size; ++i) - out << *i; - return out; -} - -inline StringData::operator bool() const noexcept -{ - return !is_null(); -} - -} // namespace realm - -#endif // REALM_STRING_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/client.hpp b/Example/Pods/Realm/include/core/realm/sync/client.hpp deleted file mode 100644 index a6e9959..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/client.hpp +++ /dev/null @@ -1,488 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2012] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_CLIENT_HPP -#define REALM_SYNC_CLIENT_HPP - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace realm { -namespace sync { - -class Client { -public: - enum class Reconnect { - /// This is the mode that should always be used in production. In this - /// mode the client uses a scheme for determining a reconnect delay that - /// prevents it from creating too many connection requests in a short - /// amount of time. - normal, - - /// Never delay reconnect attempts. For testing purposes only. - immediately - }; - - struct Config { - Config() {} - - /// The maximum number of Realm files that will be kept open - /// concurrently by this client. The client keeps a cache of open Realm - /// files for efficiency reasons. - long max_open_files = 256; - - /// An optional logger to be used by the client. If no logger is - /// specified, the client will use an instance of util::StderrLogger - /// with the log level threshold set to util::Logger::Level::info. The - /// client does not require a thread-safe logger, and it guarantees that - /// all logging happens on behalf of the thread that executes run(). - util::Logger* logger = nullptr; - - /// verify_servers_ssl_certificate controls whether the server certificate - /// is verified for SSL connections. It should always be true in production. - /// - /// A server certificate is verified by first checking that the - /// certificate has a valid signature chain back to a trust/anchor certificate, - /// and secondly checking that the host name of the Realm URL matches - /// a host name contained in the certificate. - /// The host name of the certificate is stored in either Common Name or - /// the Alternative Subject Name (DNS section). - /// - /// From the point of view of OpenSSL, setting verify_servers_ssl_certificate - /// to false means calling `SSL_set_verify()` with `SSL_VERIFY_NONE`. - /// Setting verify_servers_ssl_certificate to true means calling `SSL_set_verify()` - /// with `SSL_VERIFY_PEER`, and setting the host name using the function - /// X509_VERIFY_PARAM_set1_host() (OpenSSL version 1.0.2 or newer). - /// For other platforms, an equivalent procedure is followed. - bool verify_servers_ssl_certificate = true; - - /// ssl_trust_certificate_path is the path of a trust/anchor certificate - /// used by the client to verify the server certificate. - /// If ssl_trust_certificate_path is None (default), the default device - /// trust/anchor store is used. - util::Optional ssl_trust_certificate_path; // default None - - /// Use ports 80 and 443 by default instead of 7800 and 7801 - /// respectively. Ideally, these default ports should have been made - /// available via a different URI scheme instead (http/https or ws/wss). - bool enable_default_port_hack = true; - - /// For testing purposes only. - Reconnect reconnect = Reconnect::normal; - - /// Create a separate connection for each session. For testing purposes - /// only. - bool one_connection_per_session = false; - - /// Do not access the local file system. Sessions will act as if - /// initiated on behalf of an empty (or nonexisting) local Realm - /// file. Received DOWNLOAD messages will be accepted, but otherwise - /// ignored. No UPLOAD messages will be generated. For testing purposes - /// only. - bool dry_run = false; - }; - - /// \throw util::EventLoop::Implementation::NotAvailable if no event loop - /// implementation was specified, and - /// util::EventLoop::Implementation::get_default() throws it. - Client(Config = Config()); - Client(Client&&) noexcept; - ~Client() noexcept; - - using ErrorHandler = void(int error_code, std::string message); - - /// \brief Set a function to be called when the server reports a - /// connection-level error. - /// - /// Only connection-level errors are reported through this callback. See - /// also Session::set_error_handler(). See \ref Error (or `protocol.md`) for - /// a list of errors and their categorization. - /// - /// The callback function will always be called by the thread that executes - /// run(). If the callback function throws an exception, that exception will - /// "travel" out through run(). - /// - /// Note: Any call to this function must have returned before run() is - /// called. If this function is called multiple times, each call overrides - /// the previous setting. - /// - /// Note: This function is **not thread-safe**. - void set_error_handler(std::function); - - /// Run the internal event-loop of the client. At most one thread may - /// execute run() at any given time. The call will not return until somebody - /// calls stop(). - void run(); - - // Thread-safe - void stop() noexcept; - - /// Technically thread-safe, but the returned value is not accurate until - /// after run() has returned. - /// - /// For testing purposes. - uint_fast64_t errors_seen() const noexcept; - -private: - class Impl; - std::unique_ptr m_impl; - friend class Session; -}; - - -/// Supported protocols: -/// -/// Protocol URL scheme Default port -/// ----------------------------------------------------------------------------------- -/// realm "realm:" 7800 (80 if Client::Config::enable_default_port_hack) -/// realm_ssl "realms:" 7801 (443 if Client::Config::enable_default_port_hack) -/// -enum class Protocol { - realm, - realm_ssl -}; - - -class BadServerUrl; // Exception - - -/// Session objects must be destroyed before the Client object with which they -/// are assocoated is destroyed. -/// -/// It is an error to create two Session objects for a particular Realm file if -/// those Session objects overlap in time, or if they are associated with two -/// different Client objects that overlap in time. -/// -/// Thread-safety: It is safe for multiple threads to construct, use (with some -/// exceptions), and destroy session objects concurrently, regardless of whether -/// those session objects are associated with the same, or with different Client -/// objects. Please note that some of the public member functions are fully -/// thread-safe, while others are not. -class Session { -public: - using port_type = util::network::Endpoint::port_type; - using version_type = _impl::History::version_type; - using SyncTransactCallback = void(VersionID old_version, VersionID new_version); - using ErrorHandler = Client::ErrorHandler; - using WaitOperCompletionHandler = std::function; - - /// \brief Start a new session for the specified client-side Realm. - /// - /// Note that the session is not fully activated until you call bind(). Also - /// note that if you call set_sync_transact_callback(), it must be done - /// before calling bind(). - /// - /// \param realm_path The file-system path of a local client-side Realm - /// file. - Session(Client&, std::string realm_path); - - Session(Session&&) noexcept; - - ~Session() noexcept; - - /// \brief Set a function to be called when the local Realm has changed due - /// to integration of a downloaded changeset. - /// - /// Specify the callback function that will be called when one or more - /// transactions are performed to integrate downloaded changesets into the - /// client-side Realm, that is associated with this session. - /// - /// The callback function will always be called by the thread that executes - /// the event loop (Client::run()), but not until bind() is called. If the - /// callback function throws an exception, that exception will "travel" out - /// through Client::run(). - /// - /// Note: Any call to this function must have returned before bind() is - /// called. If this function is called multiple times, each call overrides - /// the previous setting. - /// - /// Note: This function is **not thread-safe**. That is, it is an error if - /// it is called while another thread is executing any member function on - /// the same Session object. - /// - /// CAUTION: The specified callback function may be called before the call - /// to bind() returns, and it may be called (or continue to execute) after - /// the session object is destroyed. The application must pass a handler - /// that can be safely called, and can safely continue to execute from the - /// point in time where bind() starts executing, and up until the point in - /// time where the last invocation of `clint.run()` returns. Here, `client` - /// refers to the associated Client object. - void set_sync_transact_callback(std::function); - - /// \brief Set a function to be called when an error is reported by the - /// server to have occurred in this session. - /// - /// Only session-level errors are reported through the callback. See also - /// Client::set_error_handler(). See \ref Error (or `protocol.md`) for a - /// list of errors and their categorization. - /// - /// The callback function will always be called by the thread that executes - /// the event loop (Client::run()), but not until bind() is called. If the - /// callback function throws an exception, that exception will "travel" out - /// through Client::run(). - /// - /// Note: Any call to this function must have returned before bind() is - /// called. If this function is called multiple times, each call overrides - /// the previous setting. - /// - /// Note: This function is **not thread-safe**. That is, it is an error if - /// it is called while another thread is executing any member function on - /// the same Session object. - /// - /// CAUTION: The specified callback function may be called before the call - /// to bind() returns, and it may be called (or continue to execute) after - /// the session object is destroyed. The application must pass a handler - /// that can be safely called, and can safely continue to execute from the - /// point in time where bind() starts executing, and up until the point in - /// time where the last invocation of `clint.run()` returns. Here, `client` - /// refers to the associated Client object. - void set_error_handler(std::function); - - /// @{ \brief Bind this session to the specified server side Realm. - /// - /// No communication takes place on behalf of this session before the - /// session is bound, but as soon as the session becomes bound, the server - /// will start to push changes to the client, and vice versa. - /// - /// If a callback function was set using set_sync_transact_callback(), then - /// that callback function will start to be called as changesets are - /// downloaded and integrated locally. It is important to understand that - /// callback functions are executed by the event loop thread (Client::run()) - /// and the callback function may therefore be called before bind() returns. - /// - /// Note: It is an error if this function is called more than once per - /// Session object. - /// - /// Note: This function is **not thread-safe**. That is, it is an error if - /// it is called while another thread is executing any member function on - /// the same Session object. - /// - /// \param server_url For example "realm://sync.realm.io/test". See \a - /// server_address, \a server_path, and \a server_port for information about - /// the individual components of the URL. See \ref Protocol for the list of - /// available URL schemes and the associated default ports. The 2-argument - /// version has exactly the same affect as the 5-argument version. - /// - /// \param server_address The fully qualified host name, or IP address of - /// the server. - /// - /// \param server_path The virtual path by which the server identifies the - /// Realm. This path must always be an absolute path, and must therefore - /// always contain a leading slash (`/`). Further more, each segment of the - /// virtual path must consist of one or more characters that are either - /// alpha-numeric or in (`_`, `-`, `.`), and each segment is not allowed to - /// equal `.` or `..`, and must not end with `.realm`, `.realm.lock`, or - /// `.realm.management`. These rules are necessary because the server - /// currently reserves the right to use the specified path as part of the - /// file system path of a Realm file. It is expected that these rules will - /// be significantly relaxed in the future by completely decoupling the - /// virtual paths from actual file system paths. - /// - /// \param signed_user_token A cryptographically signed token describing the - /// identity and access rights of the current user. See \ref Protocol. - /// - /// \param server_port If zero, use the default port for the specified - /// protocol. See \ref Protocol for information on default ports. - /// - /// \param protocol See \ref Protocol. - /// - /// \throw BadServerUrl if the specified server URL is malformed. - void bind(std::string server_url, std::string signed_user_token); - void bind(std::string server_address, std::string server_path, - std::string signed_user_token, port_type server_port = 0, - Protocol protocol = Protocol::realm); - /// @} - - /// \brief Refresh the user token associated with this session. - /// - /// This causes the REFRESH protocol message to be sent to the server. See - /// \ref Protocol. - /// - /// In an on-going session a client may expect its access token to expire at - /// a certain time and schedule acquisition of a fresh access token (using a - /// refresh token or by other means) in due time to provide a better user - /// experience. Without refreshing the token, the client will be notified - /// that the session is terminated due to insufficient privileges and must - /// reacquire a fresh token, which is a potentially disruptive process. - /// - /// It is an error if the user token used with this message represents a - /// different user identity than a previously used user token. The server - /// will detect this scenario and report an error. - /// - /// It is an error to call this function before calling `Client::bind()`. - /// - /// Note: This function is thread-safe. - /// - /// \param signed_user_token A cryptographically signed token describing the - /// identity and access rights of the current user. See \ref Protocol. - void refresh(std::string signed_user_token); - - /// \brief Inform the synchronization agent about changes of local origin. - /// - /// This function must be called by the application after a transaction - /// performed on its behlaf, that is, after a transaction that is not - /// performed to integrate a changeset that was downloaded from the server. - /// - /// It is an error to call this function before bind() has been called, and - /// has returned. - /// - /// Note: This function is fully thread-safe. That is, it may be called by - /// any thread, and by multiple threads concurrently. - void nonsync_transact_notify(version_type new_version); - - /// @{ \brief Wait for upload, download, or upload+download completion. - /// - /// async_wait_for_upload_completion() initiates an asynchronous wait for - /// upload to complete, async_wait_for_download_completion() initiates an - /// asynchronous wait for download to complete, and - /// async_wait_for_sync_completion() initiates an asynchronous wait for - /// upload and download to complete. - /// - /// Upload is considered complete when all non-empty changesets of local - /// origin have been uploaded to the server, and the server has acknowledged - /// reception of them. Changesets of local origin introduced after the - /// initiation of the session (after bind() is called) will generally not be - /// considered for upload unless they are announced to this client through - /// nonsync_transact_notify() prior to the initiation of the wait operation, - /// i.e., prior to the invocation of async_wait_for_upload_completion() or - /// async_wait_for_sync_completion(). Unannounced changesets may get picked - /// up, but there is no guarantee that they will be, however, if a certain - /// changeset is announced, then all previous changesets are implicitely - /// announced. Also all preexisting changesets are implicitely announced - /// when the session is initiated. - /// - /// Download is considered complete when all non-empty changesets of remote - /// origin have been downloaded from the server, and integrated into the - /// local Realm state. To know what is currently outstanding on the server, - /// the client always sends a special "marker" message to the server, and - /// waits until it has downloaded all outstanding changesets that were - /// present on the server at the time when the server received that marker - /// message. Each call to async_wait_for_download_completion() and - /// async_wait_for_sync_completion() therefore requires a full client <-> - /// server round-trip. - /// - /// If a new wait operation is initiated while other wait operations are in - /// progress, the waiting period of operations in progress may, or may not - /// get extended. The client must not assume either. The client may assume, - /// however, that async_wait_for_upload_completion() will not affect the - /// waiting period of async_wait_for_download_completion(), and vice versa. - /// - /// It is an error to call these functions before bind() has been called, - /// and has returned. - /// - /// The specified completion handlers will always be executed by the thread - /// that executes the event loop (the thread that calls Client::run()). If - /// the handler throws an exception, that exception will "travel" out - /// through Client::run(). - /// - /// If incomplete wait operations exist when the session is terminated, - /// those wait operations will be canceled. Session termination is an event - /// that happens in the context of the client's event loop thread shortly - /// after the destruction of the session object. The std::error_code - /// argument passed to the completion handler of a canceled wait operation - /// will be `util::error::operation_aborted`. For uncanceled wait operations - /// it will be `std::error_code{}`. Note that as long as the client's event - /// loop thread is running, all completion handlers will be called - /// regardless of whether the operations get canceled or not. - /// - /// CAUTION: The specified completion handlers may be called before the - /// initiation function returns (e.g. before - /// async_wait_for_upload_completion() returns), and it may be called (or - /// continue to execute) after the session object is destroyed. The - /// application must pass a handler that can be safely called, and can - /// safely continue to execute from the point in time where the initiating - /// function starts executing, and up until the point in time where the last - /// invocation of `clint.run()` returns. Here, `client` refers to the - /// associated Client object. - /// - /// Note: These functions are fully thread-safe. That is, they may be called - /// by any thread, and by multiple threads concurrently. - void async_wait_for_sync_completion(WaitOperCompletionHandler); - void async_wait_for_upload_completion(WaitOperCompletionHandler); - void async_wait_for_download_completion(WaitOperCompletionHandler); - /// @} - - /// @{ \brief Synchronous wait for upload or download completion. - /// - /// These functions are synchronous equivalents to - /// async_wait_for_upload_completion() and - /// async_wait_for_download_completion() respectively. This means that they - /// block the caller until the completion condition is satisfied, or the - /// client event loop is stopped (Client::stop()). - /// - /// It is an error to call these functions before bind() has been called, - /// and has returned. - /// - /// Note: These functions are fully thread-safe. That is, they may be called - /// by any thread, and by multiple threads concurrently. - void wait_for_upload_complete_or_client_stopped(); - void wait_for_download_complete_or_client_stopped(); - /// @} - -private: - class Impl; - Impl* m_impl; - - void async_wait_for(bool upload_completion, bool download_completion, - WaitOperCompletionHandler); -}; - - - - -// Implementation - -class BadServerUrl: public std::exception { -public: - const char* what() const noexcept override - { - return "Bad server URL"; - } -}; - -inline void Session::async_wait_for_sync_completion(WaitOperCompletionHandler handler) -{ - bool upload_completion = true, download_completion = true; - async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws -} - -inline void Session::async_wait_for_upload_completion(WaitOperCompletionHandler handler) -{ - bool upload_completion = true, download_completion = false; - async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws -} - -inline void Session::async_wait_for_download_completion(WaitOperCompletionHandler handler) -{ - bool upload_completion = false, download_completion = true; - async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws -} - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_CLIENT_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/crypto.hpp b/Example/Pods/Realm/include/core/realm/sync/crypto.hpp deleted file mode 100644 index 016543e..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/crypto.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#ifndef REALM_SYNC_CRYPTO_HPP -#define REALM_SYNC_CRYPTO_HPP - -#include -#include - -#include -#include - -namespace realm { -namespace sync { -namespace crypto { - -/// sha1() calculates the sha1 hash value of \param in_buffer of size \param -/// in_buffer_size. The value is placed in \param out_buffer. The value has -/// size 20, and the caller must ensure that \param out_buffer has size at -/// least 20. -/// sha1() throws an exception if the underlying openssl implementation -/// fails, which should just happen in case of memory allocation failure. -void sha1(const char* in_buffer, size_t in_buffer_size, char* out_buffer); - -} // namespace crypto -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_CRYPTO_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/crypto_server.hpp b/Example/Pods/Realm/include/core/realm/sync/crypto_server.hpp deleted file mode 100644 index f2ac3f0..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/crypto_server.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#ifndef REALM_SYNC_CRYPTO_SERVER_HPP -#define REALM_SYNC_CRYPTO_SERVER_HPP - -#include -#include - -#include -#include - -namespace realm { -namespace sync { - -struct CryptoError: std::runtime_error { - CryptoError(std::string message) : std::runtime_error(std::move(message)) {} -}; - -/// This class represents a public/private keypair, or more commonly a single public -/// key used for verifying signatures. -/// -/// Only RSA keys are supported for now. -/// -/// Its methods correspond roughly to the EVP_PKEY_* set of functionality found in -/// the OpenSSL library. -class PKey { -public: - PKey(PKey&&); - PKey& operator=(PKey&&); - ~PKey(); - - /// Load RSA public key from \a pemfile. - static PKey load_public(const std::string& pemfile); - /// Load RSA public/private keypair from \a pemfile. - static PKey load_private(const std::string& pemfile); - - /// Whether or not the key can be used for signing. - /// - /// True if the private part is loaded. - bool can_sign() const noexcept; - - /// Whether or not the key can be used for verifying. - /// - /// Always true for RSA keys. - bool can_verify() const noexcept; - - /// Sign \a message with the loaded key, if the private part is - /// loaded. Store the signed message as binary data in \a signature. - /// - /// If a private key is not loaded, throws an exception of type CryptoError. - void sign(BinaryData message, util::Buffer& signature) const; - - /// Verify that \a signature is a valid digest of \a message. - /// - /// Returns true if the signature is valid, otherwise false. If an error occurs while - /// attempting verification, an exception of type CryptoError is thrown. - bool verify(BinaryData message, BinaryData signature) const; - -private: - PKey(); - struct Impl; - std::unique_ptr m_impl; -}; - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_CRYPTO_SERVER_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/history.hpp b/Example/Pods/Realm/include/core/realm/sync/history.hpp deleted file mode 100644 index 3c69468..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/history.hpp +++ /dev/null @@ -1,232 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#include -#include - -#include -#include - -#ifndef REALM_SYNC_HISTORY_HPP -#define REALM_SYNC_HISTORY_HPP - -namespace realm { -namespace sync { - -/// SyncProgress is the progress sent by the server in -/// the download message. The server scans through its -/// history in connection with every download message. -/// scan_server_version is the server_version of the changeset -/// at which the server ended the scan. scan_client_version -/// is the client_version for this client that was last integrated before -/// scan_server_version. -/// latest_server_version is the end of the server history, and -/// latest_server_session_ident is the server_session_ident -/// corresponding to latest_sever_version. -/// latest_client_version is the corresponding client_version. -/// In other words, latest_client_version is the very latest version -/// of a changeset originating from this client. -/// -/// The client persists the entire progress. It is not very important to -/// persist latest_server_version, but for consistency the entire -/// progress is persisted. -struct SyncProgress { - using version_type = HistoryEntry::version_type; - - version_type scan_server_version = 0; - version_type scan_client_version = 0; - version_type latest_server_version = 0; - int_fast64_t latest_server_session_ident = 0; - version_type latest_client_version = 0; -}; - - -class SyncHistory: - public TrivialReplication { -public: - using version_type = TrivialReplication::version_type; - using file_ident_type = HistoryEntry::file_ident_type; - using SyncTransactCallback = void(VersionID old_version, VersionID new_version); - - SyncHistory(const std::string& realm_path); - - /// Get the version of the latest snapshot of the associated Realm, as well - /// as the file identifier pair and the synchronization progress pair as - /// they are stored in that snapshot. - /// - /// The returned current client version is the version of the latest - /// snapshot of the associated SharedGroup object, and is guaranteed to be - /// zero for the initial empty Realm state. - /// - /// The returned file identifier pair (server, client) is the one that was - /// last stored by set_file_ident_pair(). If no identifier pair has been - /// stored yet, \a client_file_ident is set to zero. - /// - /// The returned SyncProgress is the one that was last stored by - /// set_sync_progress(), or {} if set_sync_progress() has never been called - /// for the associated Realm file. - virtual void get_status(version_type& current_client_version, - file_ident_type& server_file_ident, - file_ident_type& client_file_ident, - int_fast64_t& client_file_ident_secret, - SyncProgress& progress) = 0; - - /// Stores the server assigned file identifier pair (server, client) in the - /// associated Realm file, such that it is available via get_status() during - /// future synchronization sessions. It is an error to set this identifier - /// pair more than once per Realm file. - /// - /// \param server_file_ident The server assigned server-side file - /// identifier. This can be any non-zero integer strictly less than 2**64. - /// The server is supposed to choose a cryptic value that cannot easily be - /// guessed by clients (intentionally or not), and its only puspose is to - /// provide a higher level of fidelity during subsequent identification of - /// the server Realm. The server does not have to guarantee that this - /// identifier is unique, but in almost all cases it will be. Since the - /// client will also always specify the path name when referring to a server - /// file, the lack of a uniqueness guarantee is effectively not a problem. - /// - /// \param client_file_ident The server assigned client-side file - /// identifier. A client-side file identifier is a non-zero positive integer - /// strictly less than 2**64. The server guarantees that all client-side - /// file identifiers generated on behalf of a particular server Realm are - /// unique with respect to each other. The server is free to generate - /// identical identifiers for two client files if they are associated with - /// different server Realms. - /// - /// The client is required to obtain the file identifiers before engaging in - /// synchronization proper, and it must store the identifiers and use - /// them to reestablish the connection between the client file and the server - /// file when engaging in future synchronization sessions. - virtual void set_file_ident_pair(file_ident_type server_file_ident, - file_ident_type client_file_ident, - int_fast64_t client_file_ident_secret) = 0; - - /// Stores the SyncProgress progress in the - /// associated Realm file in a way that makes it available via get_status() - /// during future synchronization sessions. Progress is reported by the - /// server in the DOWNLOAD message. - /// - /// See struct SyncProgress for a description of \param progress. - /// - /// `progress.scan_client_version` has an effect on the process by which - /// old history entries are discarded. - /// - /// `progress.scan_client_version` The version produced on this client by the last - /// changeset, that was sent to, and integrated by the server at the time - /// `progress.scan_server_version was produced, or zero if - /// `progress.scan_server_version` is zero. - /// - /// Since all changesets produced after `progres.scan_client_version` are potentially - /// needed during operational transformation of the next changeset received - /// from the server, the implementation of this class must promise to retain - /// all history entries produced after `progress.scan_client_version`. That is, a history - /// entry with a changeset, that produces version V, is guaranteed to be - /// retained as long as V is strictly greater than `progress.scan_client_version`. - /// - /// It is an error to specify a client version that is less than the - /// currently stored version, since there is no way to get discarded history - /// back. - virtual void set_sync_progress(SyncProgress progress) = 0; - - /// Get the first history entry whose changeset produced a version that - /// succeeds `begin_version` and, and does not succeed `end_version`, whose - /// changeset was not produced by integration of a changeset received from - /// the server, and whose changeset was not empty. - /// - /// \param begin_version, end_version The range of versions to consider. If - /// `begin_version` is equal to `end_version`, this is the empty range. If - /// `begin_version` is zero, it means that everything preceeding - /// `end_version` is to be considered, which is again the empty range if - /// `end_version` is also zero. Zero is is special value in that no - /// changeset produces that version. It is an error if `end_version` - /// preceeds `begin_version`, or if `end_version` is zero and - /// `begin_version` is not. - /// - /// \param buffer Owner of memory referenced by entry.changeset upon return. - /// - /// \return The version produced by the changeset of the located history - /// entry, or zero if no history entry exists matching the specified - /// criteria. - virtual version_type find_history_entry_for_upload(version_type begin_version, - version_type end_version, - HistoryEntry& entry, - std::unique_ptr& buffer) const = 0; - - using RemoteChangeset = Transformer::RemoteChangeset; - - /// \brief Integrate a sequence of remote changesets using a single Realm - /// transaction. - /// - /// Each changeset will be transformed as if by a call to - /// Transformer::transform_remote_changeset(), and then applied to the - /// associated Realm. - /// - /// As a final step, each changeset will be added to the local history (list - /// of applied changesets). - /// - /// \param progress is the SyncProgress received in the download message. - /// Progress will be persisted along with the changesets. - /// - /// \param num_changesets The number of passed changesets. Must be non-zero. - /// - /// \param callback An optional callback which will be called with the - /// version immediately processing the sync transaction and that of the sync - /// transaction. - /// - /// \return The new local version produced by the application of the - /// transformed changeset. - virtual version_type integrate_remote_changesets(SyncProgress progress, - const RemoteChangeset* changesets, - size_t num_changesets, - util::Logger* replay_logger, - std::function& callback) = 0; -}; - - -/// \brief Create a "sync history" implementation of the realm::Replication -/// interface. -/// -/// The main function of such an object is as a plugin for new -/// realm::SharedGroup objects. -/// -/// \param owner_is_sync_agent Must be set to true if, and only if the created -/// history object represents (is owned by) the sync agent of the specified -/// Realm file. At most one such instance is allowed to participate in a Realm -/// file access session at any point in time. Ordinarily the sync agent is -/// encapsulated by the sync::Client class, and the history instance -/// representing the agent is created transparently by sync::Client (one history -/// instance per sync::Session object). -std::unique_ptr make_sync_history(const std::string& realm_path, - bool owner_is_sync_agent = false); - - - -// Implementation - -inline SyncHistory::SyncHistory(const std::string& realm_path): - TrivialReplication(realm_path) -{ -} - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_SYNC_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/metrics.hpp b/Example/Pods/Realm/include/core/realm/sync/metrics.hpp deleted file mode 100644 index 6ce5830..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/metrics.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2012] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_METRICS_HPP -#define REALM_SYNC_METRICS_HPP - -#if REALM_HAVE_DOGLESS -# include -#endif - -namespace realm { -namespace sync { - -// FIXME: Consider adding support for specification of sample rate. The Dogless -// API already supports this. -class Metrics { -public: - /// Increment the counter identified by the specified key. - virtual void increment(const char* key) = 0; - - /// Set value of the guage identified by the specified key. - virtual void gauge(const char* key, double value) = 0; - - /// Add the specified value to the guage identified by the specified - /// key. The value is allowed to be negative. - virtual void gauge_relative(const char* key, double value) = 0; - - virtual ~Metrics() {} -}; - -#if REALM_HAVE_DOGLESS - -class DoglessMetrics: public sync::Metrics { -public: - DoglessMetrics(): - m_dogless("realm") // Throws - { -#if !REALM_PLATFORM_APPLE - m_dogless.mtu(dogless::MTU_Jumbo); -#endif - m_dogless.loop_interval(1); - } - - void increment(const char* key) override - { - const char* metric = key; - m_dogless.increment(metric); // Throws - } - - void gauge(const char* key, double value) override - { - const char* metric = key; - m_dogless.gauge(metric, value); // Throws - } - - void gauge_relative(const char* key, double value) override - { - const char* metric = key; - double amount = value; - m_dogless.gauge_relative(metric, amount); // Throws - } - -private: - dogless::BufferedStatsd m_dogless; -}; - -#endif - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_METRICS_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/protocol.hpp b/Example/Pods/Realm/include/core/realm/sync/protocol.hpp deleted file mode 100644 index bb3691a..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/protocol.hpp +++ /dev/null @@ -1,148 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2016] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_PROTOCOL_HPP -#define REALM_SYNC_PROTOCOL_HPP - -#include - -// NOTE: The protocol specification is in `/doc/protocol.md` - - -namespace realm { -namespace sync { - -// Protocol versions: -// -// 1 Initial version. -// -// 2 Introduces the UNBOUND message (sent from server to client in -// response to a BIND message). -// -// 3 Introduces the ERROR message (sent from server to client before the -// server closes a connection). Introduces MARK message from client to -// server, and MARK response message from server to client as a way for the -// client to wait for download to complete. -// -// 4 User token and signature are now passed as a single string (see -// /doc/protocol.md for details). Also, `application_ident` parameter -// removed from IDENT message. -// -// 5 IDENT message renamed to CLIENT, and ALLOC message (client->server) -// renamed to IDENT. Also, parameter added to CLIENT -// message. Also, the protocol has been changed to make the clients -// acquisition of a server allocated file identifier pair be part of a -// session from the servers point of view. File identifier and version -// parameters moved from the BIND message to a new IDENT message sent by -// client when it has obtained the file identifier pair. Both the new IDENT -// message and the ALLOC message sent by the server are now properly -// associated with a session. -// -// 6 Server session IDs have been added to the IDENT, DOWNLOAD, and PROGRESS -// messages, and the "Divergent history" error code was added as an -// indication that a server version / session ID pair does not match the -// server's history. -// -// 7 FIXME: Who introduced version 7? Please describe what changed. -// -// 8 Error code (`bad_authentication`) moved from 200-range to 300-range -// because it is now session specific. Other error codes were renumbered. -// -// 9 New format of the DOWNLOAD message to support progress reporting on the -// client -// 10 Error codes reordered (now categorized as either connection or session -// level errors). -// 11 Bugfixes in Link List and ChangeLinkTargets merge rules, that -// make previous versions incompatible. -// 12 FIXME What was 12? -// 13 Bugfixes in Link List and ChangeLinkTargets merge rules, that -// make previous versions incompatible. -// 14 Further bugfixes related to primary keys and link lists. Add support for -// LinkListSwap. -// 15 Deleting an object with a primary key deletes all objects on other -// with the same primary key. -constexpr int get_current_protocol_version() noexcept -{ - return 15; -} - -// Reserve 0 for compatibility with std::error_code. -// -// ATTENTION: Please remember to update is_session_level_error() and -// is_connection_level_error() definitions when adding/removing error codes. -enum class ProtocolError { - invalid_error = 99, // Server sent an invalid error code (ERROR) - - // Connection level and protocol errors - connection_closed = 100, // Connection closed (no error) - other_error = 101, // Other connection level error - unknown_message = 102, // Unknown type of input message - bad_syntax = 103, // Bad syntax in input message head - limits_exceeded = 104, // Limits exceeded in input message - wrong_protocol_version = 105, // Wrong protocol version (CLIENT) - bad_session_ident = 106, // Bad session identifier in input message - reuse_of_session_ident = 107, // Overlapping reuse of session identifier (BIND) - bound_in_other_session = 108, // Client file bound in other session (IDENT) - bad_message_order = 109, // Bad input message order - - // Session level errors - session_closed = 200, // Session closed (no error) - other_session_error = 201, // Other session level error - token_expired = 202, // Access token expired - bad_authentication = 203, // Bad user authentication (BIND, REFRESH) - illegal_realm_path = 204, // Illegal Realm path (BIND) - no_such_realm = 205, // No such Realm (BIND) - permission_denied = 206, // Permission denied (BIND, REFRESH) - bad_server_file_ident = 207, // Bad server file identifier (IDENT) - bad_client_file_ident = 208, // Bad client file identifier (IDENT) - bad_server_version = 209, // Bad server version (IDENT, UPLOAD) - bad_client_version = 210, // Bad client version (IDENT, UPLOAD) - diverging_histories = 211, // Diverging histories (IDENT) - bad_changeset = 212, // Bad changeset (UPLOAD) - disabled_session = 213, // Disabled session -}; - -inline constexpr bool is_session_level_error(ProtocolError error) -{ - return int(error) >= 200 && int(error) <= 213; -} - -inline constexpr bool is_connection_level_error(ProtocolError error) -{ - return int(error) >= 100 && int(error) <= 109; -} - -const char* get_error_message(ProtocolError) noexcept; - -const std::error_category& protocol_error_category() noexcept; - -std::error_code make_error_code(ProtocolError) noexcept; - -} // namespace sync -} // namespace realm - -namespace std { - -template<> struct is_error_code_enum { - static const bool value = true; -}; - -} // namespace std - -#endif // REALM_SYNC_PROTOCOL_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/server.hpp b/Example/Pods/Realm/include/core/realm/sync/server.hpp deleted file mode 100644 index 166b4be..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/server.hpp +++ /dev/null @@ -1,166 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2012] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_SERVER_HPP -#define REALM_SYNC_SERVER_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace realm { -namespace sync { - -class Server { -public: - struct Config { - Config() {} - - /// The maximum number of Realm files that will be kept open - /// concurrently by this server. The server keeps a cache of open Realm - /// files for efficiency reasons. - long max_open_files = 256; - - /// An optional logger to be used by the server. If no logger is - /// specified, the server will use an instance of util::StderrLogger - /// with the log level threshold set to util::Logger::Level::info. The - /// server does not require a thread-safe logger, and it guarantees that - /// all logging happens on behalf of start() and run() (which are not - /// allowed to execute concurrently). - util::Logger* logger = nullptr; - - /// An optional sink for recording metrics about the internal operation - /// of the server. Below is a list of counters and gauges that are - /// updated by the server. The server may or may not update additional - /// counters and gauges. - /// - /// Statistics counters Incremented when - /// ------------------------------------------------------------------------ - /// server.started The server was started - /// connection.started A new client connection was established - /// connection.terminated A client connection was terminated - /// session.started A new session was started - /// session.terminated A session was terminated - /// connection.read.failed A connection was closed due to read error - /// connection.write.failed A connection was closed due to write error - /// protocol.upload.received An UPLOAD message was received - /// protocol.download.sent A DOWNLOAD message was sent - /// protocol.connection.errored Connection level protocol error occurred - /// protocol.session.errored Session level protocol error occurred - /// - /// Statistics gauges Continuously updated to reflect - /// -------------------------------------------------------------------------- - /// connection.opened The current total number of connections - /// session.opened The current total number of sessions - /// - Metrics* metrics = nullptr; - - /// FIXME: This seems to be related to the dashboard feature, but it - /// would be nice with some additional explanation (Sebastian). - const char* stats_db = nullptr; - - /// The address at which the listening socket is bound. - /// The address can be a name or on numerical form. - /// Use "localhost" to listen on the loopback interface. - std::string listen_address; - - /// The port at which the listening socket is bound. - /// The port can be a name or on numerical form. - /// Use the empty string to have the system assign a dynamic - /// listening port. - std::string listen_port; - - bool reuse_address = true; - - /// The listening socket accepts TLS/SSL connections if `ssl` is - /// true, and non-secure tcp connections otherwise. - bool ssl = false; - - /// The path of the certificate that will be sent to clients during - /// the SSL/TLS handshake. - /// - /// From the point of view of OpenSSL, this file will be passed to - /// `SSL_CTX_use_certificate_chain_file()`. - /// - /// This option is ignore if `ssl` is false. - std::string ssl_certificate_path; - - /// The path of the private key corresponding to the certificate. - /// - /// From the point of view of OpenSSL, this file will be passed to - /// `SSL_CTX_use_PrivateKey_file()`. - /// - /// This option is ignore if `ssl` is false. - std::string ssl_certificate_key_path; - }; - - Server(const std::string& root_dir, util::Optional public_key, Config = Config()); - Server(Server&&) noexcept; - ~Server() noexcept; - - /// start() binds a listening socket to the address and port specified in - /// Config and starts accepting connections. - /// The resolved endpoint (including the dynamically assigned port, if requested) - /// can be obtained by calling listen_endpoint(). - /// This can be done immediately after start() returns. - void start(); - - /// A helper function, for backwards compatibility, that starts a listening - /// socket without SSL at the specified address and port. - void start(const std::string& listen_address, - const std::string& listen_port, - bool reuse_address = true); - - /// Return the resolved and bound endpoint of the listening socket. - util::network::Endpoint listen_endpoint() const; - - /// Run the internal event-loop of the server. At most one thread may - /// execute run() at any given time. It is an error if run() is called - /// before start() has been successfully executed. The call to run() will - /// not return until somebody calls stop(). - void run(); - - /// Stop any thread that is currently executing run(). This function may be - /// called by any thread. - void stop() noexcept; - - /// Must not be called while run() is executing. - uint_fast64_t errors_seen() const noexcept; - - /// Initialise the directory structure as required for correct operation of - /// the server. This is a static function, as it should be run on the \a - /// root_path prior to instantiating the \c Server object. - static void init_directory_structure(const std::string& root_path, util::Logger& logger); - - -private: - class Implementation; - std::unique_ptr m_impl; -}; - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_SERVER_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/server_configuration.hpp b/Example/Pods/Realm/include/core/realm/sync/server_configuration.hpp deleted file mode 100644 index e295b4f..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/server_configuration.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_SERVER_CONFIGURATION_HPP -#define REALM_SYNC_SERVER_CONFIGURATION_HPP - -// Realm headers -#include -#include - -namespace realm { -namespace config { - -struct Configuration { - std::string listen_address = "127.0.0.1"; - std::string listen_port = ""; // Empty means choose default based on `ssl`. - realm::util::Optional root_dir; - std::string user_data_dir; - std::string internal_data_dir; - realm::util::Optional public_key_path; - realm::util::Optional config_file_path; - bool reuse_address = true; - bool disable_sync = false; - realm::util::Logger::Level log_level = realm::util::Logger::Level::info; - realm::util::Optional log_path; - std::string stats_db_path; - long max_open_files = 256; - bool ssl = false; - std::string ssl_certificate_path; - std::string ssl_certificate_key_path; -}; - -void show_help(const std::string& program_name); -Configuration build_configuration(int argc, char* argv[]); -Configuration load_configuration(std::string configuration_file_path); - -} // namespace config -} // namespace realm - -#endif // REALM_SYNC_SERVER_CONFIGURATION_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/transform.hpp b/Example/Pods/Realm/include/core/realm/sync/transform.hpp deleted file mode 100644 index 5d9b115..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/transform.hpp +++ /dev/null @@ -1,371 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2015] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ - -#ifndef REALM_SYNC_TRANSFORM_HPP -#define REALM_SYNC_TRANSFORM_HPP - -#include - -#include -#include -#include - -namespace realm { -namespace sync { - -class HistoryEntry { -public: - using timestamp_type = uint_fast64_t; - using file_ident_type = uint_fast64_t; - using version_type = _impl::History::version_type; - - /// The time of origination of the changes referenced by this history entry, - /// meassured as the number of milliseconds since 2015-01-01T00:00:00Z, not - /// including leap seconds. For changes of local origin, this is the local - /// time at the point when the local transaction was committed. For changes - /// of remote origin, it is the remote time of origin at the client - /// identified by `origin_client_file_ident`. - /// - /// All clients that will be, or are already participating in - /// synchronization must guarantee that their local history is causally - /// consistent. The convergence guarantee offered by the merge system relies - /// strongly on this. - /// - /// FIXME: In its current form, the merge algorithm seems to achieve - /// convergence even without causal consistency. Figure out whether we still - /// want to require it, and if so, why. - /// - /// **Definition:** The local history is *causally consistent* if, and only - /// if every entry, referring to changes of local origin, has an effective - /// timestamp, which is greater than, or equal to the effective timestamp of - /// all preceding entries in the local history. - /// - /// **Definition:** The *effective timestamp* of a history entry is the pair - /// `(origin_timestamp, origin_client_file_ident)` endowed with the standard - /// lexicographic order. Note that this implies that it is impossible for - /// two entries to have equal effective timestamps if they originate from - /// different clients. - timestamp_type origin_timestamp; - - /// For changes of local origin, `origin_client_file_ident` is always - /// zero. For changes of remote origin, this history entry was produced by - /// the integration of a changeset received from a remote peer P. In some - /// cases, that changeset may itself have been produced by the integration - /// on P of a changeset received from another remote peer. In any case, as - /// long as these changes are of remote origin, `origin_client_file_ident` - /// identifies the peer on which they originated, which may or may not be P. - /// - /// More concretely, on the server-side, the remote peer is a client, and - /// and the changes always originate from that client, so - /// `origin_client_file_ident` always refer to that client. Conversely, on - /// the client-side, the remote peer is the server, and the server received - /// the original changeset from a client, so `origin_client_file_ident` - /// refers to that client. - /// - /// Note that *peer* is used colloquially here to refer to a particular - /// synchronization participant. In reality, a synchronization participant - /// is either a server-side file, or a particular client-side file - /// associated with that server-side file. To make things even more - /// confusing, a single client application may contain multiple client-side - /// files associated with the same server-side file. In the same vein, - /// *client* should be understood as client-side file, and *remote peer* as - /// any other file from the set of associated files, even other such files - /// contained within the same client application, if there are any. - file_ident_type origin_client_file_ident; - - /// For changes of local origin, `remote_version` is the version produced on - /// the remote peer by the last changeset integrated locally prior to the - /// production of the changeset referenced by this history entry, or zero if - /// no remote changeset was integrated yet. This only makes sense when there - /// is a unique remote peer, and since that is not the case on the server, - /// the server cannot be the originator of any changes. - /// - /// For changes of remote origin, this history entry was produced by the - /// integration of a changeset directly received from a remote peer P, and - /// `remote_version` is then the version produced on P by that - /// changeset. Note that such changes may have originated from a different - /// peer (not P), but `remote_version` will still be the version produced on - /// P. - /// - /// More concretely, on the server-side, the remote peer is a client, and - /// the changes always originate from that client, and `remote_version` is - /// the `` specified in an UPLOAD message of the - /// client-server communication protocol. Conversely, for changes of remote - /// origin on the client-side, the remote peer is the server, and - /// `remote_version` is the specified in a received - /// DOWNLOAD message. - version_type remote_version; - - /// Referenced memory is not owned by this class. - BinaryData changeset; -}; - - -/// The interface between the sync history and the operational transformer -/// (Transformer). -class TransformHistory { -public: - using timestamp_type = HistoryEntry::timestamp_type; - using file_ident_type = HistoryEntry::file_ident_type; - using version_type = HistoryEntry::version_type; - - /// Get the first history entry whose changeset produced a version that - /// succeeds `begin_version` and, and does not succeed `end_version`, and - /// whose changeset was not produced by integration of a changeset received - /// from the specified remote peer. - /// - /// The ownership of the memory referenced by `entry.changeset` is **not** - /// passed to the caller upon return. The callee retains ownership. - /// - /// \param begin_version, end_version The range of versions to consider. If - /// `begin_version` is equal to `end_version`, this is the empty range. If - /// `begin_version` is zero, it means that everything preceeding - /// `end_version` is to be considered, which is again the empty range if - /// `end_version` is also zero. Zero is is special value in that no - /// changeset produces that version. It is an error if `end_version` - /// preceeds `begin_version`, or if `end_version` is zero and - /// `begin_version` is not. - /// - /// \param not_from_remote_client_file_ident Skip entries whose changeset is - /// produced by integration of changesets received from this remote - /// peer. Zero if the remote peer is the server, otherwise the peer - /// identifier of a client. - /// - /// \param only_nonempty Skip entries with empty changesets. - /// - /// \return The version produced by the changeset of the located history - /// entry, or zero if no history entry exists matching the specified - /// criteria. - virtual version_type find_history_entry(version_type begin_version, version_type end_version, - file_ident_type not_from_remote_client_file_ident, - bool only_nonempty, - HistoryEntry& entry) const noexcept = 0; - - /// Copy a contiguous sequence of bytes from the specified reciprocally - /// transformed changeset into the specified buffer. The targeted history - /// entry is the one whose untransformed changeset produced the specified - /// version. Copying starts at the specified offset within the transform, - /// and will continue until the end of the transform or the end of the - /// buffer, whichever comes first. The first copied byte is always placed in - /// `buffer[0]`. The number of copied bytes is returned. - /// - /// \param remote_client_file_ident Zero if the remote peer is the server, - /// otherwise the peer identifier of a client. - virtual size_t read_reciprocal_transform(version_type version, - file_ident_type remote_client_file_ident, - size_t offset, char* buffer, size_t size) const = 0; - - /// Replace a contiguous chunk of bytes within the specified reciprocally - /// transformed changeset. The targeted history entry is the one whose - /// untransformed changeset produced the specified version. If the new chunk - /// has a different size than the on it replaces, subsequent bytes (those - /// beyond the end of the replaced chunk) are shifted to lower or higher - /// offsets accordingly. If `replaced_size` is equal to `size_t(-1)`, the - /// replaced chunk extends from `offset` to the end of the transform. Let - /// `replaced_size_2` be the actual size of the replaced chunk, then the - /// total number of bytes in the transform will increase by `size - - /// replaced_size_2`. It is an error if `replaced_size` is not `size_t(-1)` - /// and `offset + replaced_size` is greater than the size of the transform. - /// - /// \param remote_client_file_ident See read_reciprocal_transform(). - /// - /// \param offset The index of the first replaced byte relative to the - /// beginning of the transform. - /// - /// \param replaced_size The number of bytes in the replaced chunk. - /// - /// \param data The buffer holding the replacing chunk. - /// - /// \param size The number of bytes in the replacing chunk, which is also - /// the number of bytes that will be read from the specified buffer. - virtual void write_reciprocal_transform(version_type version, - file_ident_type remote_client_file_ident, - size_t offset, size_t replaced_size, - const char* data, size_t size) = 0; - - virtual ~TransformHistory() noexcept {} - -protected: - static bool register_local_time(timestamp_type local_timestamp, - timestamp_type& timestamp_threshold) noexcept; - - static bool register_remote_time(timestamp_type remote_timestamp, - timestamp_type& timestamp_threshold) noexcept; -}; - - -class TransformError; // Exception - - -class Transformer { -public: - using timestamp_type = HistoryEntry::timestamp_type; - using file_ident_type = HistoryEntry::file_ident_type; - using version_type = HistoryEntry::version_type; - - struct RemoteChangeset { - /// The version produced on the remote peer by this changeset. - /// - /// On the server, the remote peer is the client from which the - /// changeset originated, and `remote_version` is the client version - /// produced by the changeset on that client. - /// - /// On a client, the remote peer is the server, and `remote_version` is - /// the server version produced by this changeset on the server. Since - /// the server is never the originator of changes, this changeset must - /// in turn have been produced on the server by integration of a - /// changeset uploaded by some other client. - version_type remote_version; - - /// The last local version that has been integrated into - /// `remote_version`. - /// - /// A local version, L, has been integrated into a remote version, R, - /// when, and only when L is the latest local version such that all - /// preceeding changesets in the local history have been integrated by - /// the remote peer prior to R. - /// - /// On the server, this is the last server version integrated into the - /// client version `remote_version`. On a client, it is the last client - /// version integrated into the server version `remote_version`. - version_type last_integrated_local_version; - - /// The changeset itself. - BinaryData data; - - /// Same meaning as `HistoryEntry::origin_timestamp`. - timestamp_type origin_timestamp; - - /// Same meaning as `HistoryEntry::origin_client_file_ident`. - file_ident_type origin_client_file_ident; - - RemoteChangeset(version_type rv, version_type lv, BinaryData d, timestamp_type ot, - file_ident_type fi); - }; - - /// Produce an operationally transformed version of the specified changeset, - /// which is assumed to be of remote origin, and received from remote peer - /// P. Note that P is not necessarily the peer from which the changes - /// originated. - /// - /// Operational transformation is carried out between the specified - /// changeset and all causally unrelated changesets in the local history. A - /// changeset in the local history is causally unrelated if, and only if it - /// occurs after the local changeset that produced - /// `remote_changeset.last_integrated_local_version` and is not a produced - /// by integration of a changeset received from P. This assumes that - /// `remote_changeset.last_integrated_local_version` is set to the local - /// version produced by the last local changeset, that was integrated by P - /// before P produced the specified changeset. - /// - /// The operational transformation is reciprocal (two-way), so it also - /// transforms the causally unrelated local changesets. This process does - /// not modify the history itself (the changesets available through - /// TransformHistory::get_history_entry()), instead the reciprocally - /// transformed changesets are stored separately, and individually for each - /// remote peer, such that they can participate in transformation of the - /// next incoming changeset from P. Note that the peer identifier of P can - /// be derived from `origin_client_file_ident` and information about whether - /// the local peer is a server or a client. - /// - /// In general, if A and B are two causally unrelated (alternative) - /// changesets based on the same version V, then the operational - /// transformation between A and B produces changesets A' and B' such that - /// both of the concatenated changesets A + B' and B + A' produce the same - /// final state when applied to V. Operational transformation is meaningful - /// only when carried out between alternative changesets based on the same - /// version. - /// - /// \return The size of the transformed version of the specified - /// changeset. Upon return, the changeset itself is stored in the specified - /// output buffer. - /// - /// \throw TransformError Thrown if operational transformation fails due to - /// a problem with the specified changeset. - virtual size_t transform_remote_changeset(TransformHistory&, - version_type current_local_version, - RemoteChangeset changeset, - util::Buffer& output_buffer) = 0; - - virtual ~Transformer() noexcept {} -}; - - -/// \param local_client_file_ident The server assigned local client file -/// identifier. This must be zero on the server-side, and only on the -/// server-side. -std::unique_ptr make_transformer(Transformer::file_ident_type local_client_file_ident); - - - - -// Implementation - -inline bool TransformHistory::register_local_time(timestamp_type local_timestamp, - timestamp_type& timestamp_threshold) noexcept -{ - // Needed to ensure causal consistency. This also guards against - // nonmonotonic local time. - if (timestamp_threshold < local_timestamp) { - timestamp_threshold = local_timestamp; - return true; - } - return false; -} - -inline bool TransformHistory::register_remote_time(timestamp_type remote_timestamp, - timestamp_type& timestamp_threshold) noexcept -{ - // To ensure causal consistency, we need to know the latest remote (or - // local) timestamp seen so far. Adding one to the incoming remote - // timestamp, before using it to bump the `timestamp_threshold`, is a - // simple way of ensuring not only proper ordering among timestamps, but - // also among 'effective timestamps' (which is required), regardless of the - // values of the assiciated client file identifiers. - if (timestamp_threshold < remote_timestamp + 1) { - timestamp_threshold = remote_timestamp + 1; - return true; - } - return false; -} - -class TransformError: public std::runtime_error { -public: - TransformError(const std::string& message): - std::runtime_error(message) - { - } -}; - -inline Transformer::RemoteChangeset::RemoteChangeset(version_type rv, version_type lv, - BinaryData d, timestamp_type ot, - file_ident_type fi): - remote_version(rv), - last_integrated_local_version(lv), - data(d), - origin_timestamp(ot), - origin_client_file_ident(fi) -{ -} - -} // namespace sync -} // namespace realm - -#endif // REALM_SYNC_TRANSFORM_HPP diff --git a/Example/Pods/Realm/include/core/realm/sync/version.hpp b/Example/Pods/Realm/include/core/realm/sync/version.hpp deleted file mode 100644 index 95207f0..0000000 --- a/Example/Pods/Realm/include/core/realm/sync/version.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/************************************************************************* - * - * REALM CONFIDENTIAL - * __________________ - * - * [2011] - [2013] Realm Inc - * All Rights Reserved. - * - * NOTICE: All information contained herein is, and remains - * the property of Realm Incorporated and its suppliers, - * if any. The intellectual and technical concepts contained - * herein are proprietary to Realm Incorporated - * and its suppliers and may be covered by U.S. and Foreign Patents, - * patents in process, and are protected by trade secret or copyright law. - * Dissemination of this information or reproduction of this material - * is strictly forbidden unless prior written permission is obtained - * from Realm Incorporated. - * - **************************************************************************/ -#ifndef REALM_SYNC_VERSION_HPP -#define REALM_SYNC_VERSION_HPP - -#include - -#define REALM_SYNC_VER_MAJOR 1 -#define REALM_SYNC_VER_MINOR 0 -#define REALM_SYNC_VER_PATCH 0-BETA-5.1 -#define REALM_SYNC_PRODUCT_NAME "realm-sync" - -#define REALM_SYNC_VER_STRING REALM_QUOTE(REALM_SYNC_VER_MAJOR) "." \ - REALM_QUOTE(REALM_SYNC_VER_MINOR) "." REALM_QUOTE(REALM_SYNC_VER_PATCH) -#define REALM_SYNC_VER_CHUNK "[" REALM_SYNC_PRODUCT_NAME "-" REALM_SYNC_VER_STRING "]" - -#endif // REALM_SYNC_VERSION_HPP diff --git a/Example/Pods/Realm/include/core/realm/table.hpp b/Example/Pods/Realm/include/core/realm/table.hpp deleted file mode 100644 index 01c44ac..0000000 --- a/Example/Pods/Realm/include/core/realm/table.hpp +++ /dev/null @@ -1,2439 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_TABLE_HPP -#define REALM_TABLE_HPP - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace realm { - -class BacklinkColumn; -class BinaryColumy; -class ConstTableView; -class Group; -class LinkColumn; -class LinkColumnBase; -class LinkListColumn; -class LinkView; -class SortDescriptor; -class StringIndex; -class TableView; -class TableViewBase; -class TimestampColumn; -template -class Columns; -template -class SubQuery; -struct LinkTargetInfo; - -struct Link { -}; -typedef Link LinkList; -typedef Link BackLink; - -namespace _impl { -class TableFriend; -} - -class Replication; - - -/// The Table class is non-polymorphic, that is, it has no virtual -/// functions. This is important because it ensures that there is no run-time -/// distinction between a Table instance and an instance of any variation of -/// BasicTable, and this, in turn, makes it valid to cast a pointer from -/// Table to BasicTable even when the instance is constructed as a Table. Of -/// course, this also assumes that BasicTable<> is non-polymorphic, has no -/// destructor, and adds no extra data members. -/// -/// FIXME: Table assignment (from any group to any group) could be made aliasing -/// safe as follows: Start by cloning source table into target allocator. On -/// success, assign, and then deallocate any previous structure at the target. -/// -/// FIXME: It might be desirable to have a 'table move' feature between two -/// places inside the same group (say from a subtable or a mixed column to group -/// level). This could be done in a very efficient manner. -/// -/// FIXME: When compiling in debug mode, all public non-static table functions -/// should REALM_ASSERT(is_attached()). -class Table { -public: - /// Construct a new freestanding top-level table with static - /// lifetime. - /// - /// This constructor should be used only when placing a table - /// instance on the stack, and it is then the responsibility of - /// the application that there are no objects of type TableRef or - /// ConstTableRef that refer to it, or to any of its subtables, - /// when it goes out of scope. To create a top-level table with - /// dynamic lifetime, use Table::create() instead. - Table(Allocator& = Allocator::get_default()); - - /// Construct a copy of the specified table as a new freestanding - /// top-level table with static lifetime. - /// - /// This constructor should be used only when placing a table - /// instance on the stack, and it is then the responsibility of - /// the application that there are no objects of type TableRef or - /// ConstTableRef that refer to it, or to any of its subtables, - /// when it goes out of scope. To create a top-level table with - /// dynamic lifetime, use Table::copy() instead. - Table(const Table&, Allocator& = Allocator::get_default()); - - ~Table() noexcept; - - Allocator& get_alloc() const; - - /// Construct a new freestanding top-level table with dynamic lifetime. - static TableRef create(Allocator& = Allocator::get_default()); - - /// Construct a copy of the specified table as a new freestanding top-level - /// table with dynamic lifetime. - TableRef copy(Allocator& = Allocator::get_default()) const; - - /// Returns true if, and only if this accessor is currently attached to an - /// underlying table. - /// - /// A table accessor may get detached from the underlying row for various - /// reasons (see below). When it does, it no longer refers to anything, and - /// can no longer be used, except for calling is_attached(). The - /// consequences of calling other non-static functions on a detached table - /// accessor are unspecified. Table accessors obtained by calling functions in - /// the Realm API are always in the 'attached' state immediately upon - /// return from those functions. - /// - /// A table accessor of a free-standing table never becomes detached (except - /// during its eventual destruction). A group-level table accessor becomes - /// detached if the underlying table is removed from the group, or when the - /// group accessor is destroyed. A subtable accessor becomes detached if the - /// underlying subtable is removed, or if the parent table accessor is - /// detached. A table accessor does not become detached for any other reason - /// than those mentioned here. - /// - /// FIXME: High level language bindings will probably want to be able to - /// explicitely detach a group and all tables of that group if any modifying - /// operation fails (e.g. memory allocation failure) (and something similar - /// for freestanding tables) since that leaves the group in state where any - /// further access is disallowed. This way they will be able to reliably - /// intercept any attempt at accessing such a failed group. - /// - /// FIXME: The C++ documentation must state that if any modifying operation - /// on a group (incl. tables, subtables, and specs) or on a free standing - /// table (incl. subtables and specs) fails, then any further access to that - /// group (except ~Group()) or freestanding table (except ~Table()) has - /// undefined behaviour and is considered an error on behalf of the - /// application. Note that even Table::is_attached() is disallowed in this - /// case. - bool is_attached() const noexcept; - - /// Get the name of this table, if it has one. Only group-level tables have - /// names. For a table of any other kind, this function returns the empty - /// string. - StringData get_name() const noexcept; - - // Whether or not elements can be null. - bool is_nullable(size_t col_ndx) const; - - //@{ - /// Conventience functions for inspecting the dynamic table type. - /// - /// These functions behave as if they were called on the descriptor returned - /// by get_descriptor(). - size_t get_column_count() const noexcept; - DataType get_column_type(size_t column_ndx) const noexcept; - StringData get_column_name(size_t column_ndx) const noexcept; - size_t get_column_index(StringData name) const noexcept; - //@} - - //@{ - /// Convenience functions for manipulating the dynamic table type. - /// - /// These function must be called only for tables with independent dynamic - /// type. A table has independent dynamic type if the function - /// has_shared_type() returns false. A table that is a direct member of a - /// group has independent dynamic type. So does a free-standing table, and a - /// subtable in a column of type 'mixed'. All other tables have shared - /// dynamic type. The consequences of calling any of these functions for a - /// table with shared dynamic type are undefined. - /// - /// Apart from that, these functions behave as if they were called on the - /// descriptor returned by get_descriptor(). Note especially that the - /// `_link` suffixed functions must be used when inserting link-type - /// columns. - /// - /// If you need to change the shared dynamic type of the subtables in a - /// subtable column, consider using the API offered by the Descriptor class. - /// - /// \sa has_shared_type() - /// \sa get_descriptor() - - size_t add_column(DataType type, StringData name, bool nullable = false, DescriptorRef* subdesc = nullptr); - void insert_column(size_t column_ndx, DataType type, StringData name, bool nullable = false, - DescriptorRef* subdesc = nullptr); - - // Todo, these prototypes only exist for backwards compatibility. We should remove them because they are error - // prone (optional arguments and implicit bool to null-ptr conversion) - size_t add_column(DataType type, StringData name, DescriptorRef* subdesc) - { - return add_column(type, name, false, subdesc); - } - void insert_column(size_t column_ndx, DataType type, StringData name, DescriptorRef* subdesc) - { - insert_column(column_ndx, type, name, false, subdesc); - } - - size_t add_column_link(DataType type, StringData name, Table& target, LinkType link_type = link_Weak); - void insert_column_link(size_t column_ndx, DataType type, StringData name, Table& target, - LinkType link_type = link_Weak); - void remove_column(size_t column_ndx); - void rename_column(size_t column_ndx, StringData new_name); - //@} - - //@{ - - /// has_search_index() returns true if, and only if a search index has been - /// added to the specified column. Rather than throwing, it returns false if - /// the table accessor is detached or the specified index is out of range. - /// - /// add_search_index() adds a search index to the specified column of this - /// table. It has no effect if a search index has already been added to the - /// specified column (idempotency). - /// - /// remove_search_index() removes the search index from the specified column - /// of this table. It has no effect if the specified column has no search - /// index. The search index cannot be removed from the primary key of a - /// table. - /// - /// This table must be a root table; that is, it must have an independent - /// descriptor. Freestanding tables, group-level tables, and subtables in a - /// column of type 'mixed' are all examples of root tables. See add_column() - /// for more on this. - /// - /// \param column_ndx The index of a column of this table. - - bool has_search_index(size_t column_ndx) const noexcept; - void add_search_index(size_t column_ndx); - void remove_search_index(size_t column_ndx); - - //@} - - //@{ - /// Get the dynamic type descriptor for this table. - /// - /// Every table has an associated descriptor that specifies its dynamic - /// type. For simple tables, that is, tables without subtable columns, the - /// dynamic type can be inspected and modified directly using member - /// functions such as get_column_count() and add_column(). For more complex - /// tables, the type is best managed through the associated descriptor - /// object which is returned by this function. - /// - /// \sa has_shared_type() - DescriptorRef get_descriptor(); - ConstDescriptorRef get_descriptor() const; - //@} - - //@{ - /// Get the dynamic type descriptor for the column with the - /// specified index. That column must have type 'table'. - /// - /// This is merely a shorthand for calling `get_subdescriptor(column_ndx)` - /// on the descriptor returned by `get_descriptor()`. - DescriptorRef get_subdescriptor(size_t column_ndx); - ConstDescriptorRef get_subdescriptor(size_t column_ndx) const; - //@} - - //@{ - /// Get access to an arbitrarily nested dynamic type descriptor. - /// - /// The returned descriptor is the one you would get by calling - /// Descriptor::get_subdescriptor() once for each entry in the specified - /// path, starting with the descriptor returned by get_descriptor(). The - /// path is allowed to be empty. - typedef std::vector path_vec; - DescriptorRef get_subdescriptor(const path_vec& path); - ConstDescriptorRef get_subdescriptor(const path_vec& path) const; - //@} - - //@{ - /// Convenience functions for manipulating nested table types. - /// - /// These functions behave as if they were called on the descriptor returned - /// by `get_subdescriptor(path)`. These function must be called only on - /// tables with independent dynamic type. - /// - /// \return The value returned by add_subcolumn(), is the index of - /// the added column within the descriptor referenced by the - /// specified path. - /// - /// \sa Descriptor::add_column() - /// \sa has_shared_type() - size_t add_subcolumn(const path_vec& path, DataType type, StringData name); - void insert_subcolumn(const path_vec& path, size_t column_ndx, DataType type, StringData name); - void remove_subcolumn(const path_vec& path, size_t column_ndx); - void rename_subcolumn(const path_vec& path, size_t column_ndx, StringData new_name); - //@} - - /// Does this table share its type with other tables? - /// - /// Tables that are direct members of groups have independent - /// dynamic types. The same is true for free-standing tables and - /// subtables in coulmns of type 'mixed'. For such tables, this - /// function returns false. - /// - /// When a table has a column of type 'table', the cells in that - /// column contain subtables. All those subtables have the same - /// dynamic type, and they share a single type descriptor. For all - /// such subtables, this function returns true. See - /// Descriptor::is_root() for more on this. - /// - /// Please note that Table functions that modify the dynamic type - /// directly, such as add_column(), are only allowed to be used on - /// tables with non-shared type. If you need to modify a shared - /// type, you will have to do that through the descriptor returned - /// by get_descriptor(), but note that it will then affect all the - /// tables sharing that descriptor. - /// - /// \sa get_descriptor() - /// \sa Descriptor::is_root() - bool has_shared_type() const noexcept; - - - template - Columns column(size_t column); // FIXME: Should this one have been declared noexcept? - template - Columns column(const Table& origin, size_t origin_column_ndx); - - template - SubQuery column(size_t column, Query subquery); - template - SubQuery column(const Table& origin, size_t origin_column_ndx, Query subquery); - - // Table size and deletion - bool is_empty() const noexcept; - size_t size() const noexcept; - - typedef BasicRowExpr
RowExpr; - typedef BasicRowExpr ConstRowExpr; - - RowExpr get(size_t row_ndx) noexcept; - ConstRowExpr get(size_t row_ndx) const noexcept; - - RowExpr front() noexcept; - ConstRowExpr front() const noexcept; - - RowExpr back() noexcept; - ConstRowExpr back() const noexcept; - - RowExpr operator[](size_t row_ndx) noexcept; - ConstRowExpr operator[](size_t row_ndx) const noexcept; - - - //@{ - - /// Row handling. - /// - /// remove() removes the specified row from the table and shifts all rows at - /// higher index to fill the vacated slot. This operation assumes that the - /// table is ordered, and it is therefore allowed only on tables **without** - /// link columns, as link columns are only allowed in unordered tables. - /// - /// move_last_over() removes the specified row from the table, and if it is - /// not the last row in the table, it then moves the last row into the - /// vacated slot. This operation assumes that the table is unordered, and it - /// may therfore be used on tables with link columns. - /// - /// The removal of a row from an unordered table (move_last_over()) may - /// cause other linked rows to be cascade-removed. The clearing of a table - /// may also cause linked rows to be cascade-removed, but in this respect, - /// the effect is exactly as if each row had been removed individually. See - /// Descriptor::set_link_type() for details. - - size_t add_empty_row(size_t num_rows = 1); - void insert_empty_row(size_t row_ndx, size_t num_rows = 1); - void remove(size_t row_ndx); - void remove_last(); - void move_last_over(size_t row_ndx); - void clear(); - void swap_rows(size_t row_ndx_1, size_t row_ndx_2); - //@} - - /// Replaces all links to \a row_ndx with links to \a new_row_ndx. - /// - /// This operation is usually followed by Table::move_last_over() - /// as part of Table::set_int_unique() or Table::set_string_unique() - /// or Table::set_null_unique() detecting a collision. - /// - /// \sa Table::move_last_over() - /// \sa Table::set_int_unique() - /// \sa Table::set_string_unique() - /// \sa Table::set_null_unique() - void merge_rows(size_t row_ndx, size_t new_row_ndx); - - // Get cell values. Will assert if the requested type does not match the column type - int64_t get_int(size_t column_ndx, size_t row_ndx) const noexcept; - bool get_bool(size_t column_ndx, size_t row_ndx) const noexcept; - OldDateTime get_olddatetime(size_t column_ndx, size_t row_ndx) const noexcept; - float get_float(size_t column_ndx, size_t row_ndx) const noexcept; - double get_double(size_t column_ndx, size_t row_ndx) const noexcept; - StringData get_string(size_t column_ndx, size_t row_ndx) const noexcept; - BinaryData get_binary(size_t column_ndx, size_t row_ndx) const noexcept; - Mixed get_mixed(size_t column_ndx, size_t row_ndx) const noexcept; - DataType get_mixed_type(size_t column_ndx, size_t row_ndx) const noexcept; - Timestamp get_timestamp(size_t column_ndx, size_t row_ndx) const noexcept; - - template - T get(size_t c, size_t r) const noexcept; - - size_t get_link(size_t column_ndx, size_t row_ndx) const noexcept; - bool is_null_link(size_t column_ndx, size_t row_ndx) const noexcept; - LinkViewRef get_linklist(size_t column_ndx, size_t row_ndx); - ConstLinkViewRef get_linklist(size_t column_ndx, size_t row_ndx) const; - size_t get_link_count(size_t column_ndx, size_t row_ndx) const noexcept; - bool linklist_is_empty(size_t column_ndx, size_t row_ndx) const noexcept; - bool is_null(size_t column_ndx, size_t row_ndx) const noexcept; - - TableRef get_link_target(size_t column_ndx) noexcept; - ConstTableRef get_link_target(size_t column_ndx) const noexcept; - - template - typename T::RowAccessor get_link_accessor(size_t column_ndx, size_t row_ndx); - - //@{ - - /// Set cell values. - /// - /// It is an error to specify a column index, row index, or string position - /// that is out of range. - /// - /// The number of bytes in a string value must not exceed `max_string_size`, - /// and the number of bytes in a binary data value must not exceed - /// `max_binary_size`. String must also contain valid UTF-8 encodings. These - /// requirements also apply when modifying a string with insert_substring() - /// and remove_substring(), and for strings in a mixed columnt. Passing, or - /// producing an oversized string or binary data value will cause an - /// exception to be thrown. - /// - /// The "unique" variants (set_int_unique(), set_string_unique(), set_null_unique()) - /// are intended to be used in the implementation of primary key support. They - /// check if the given column already contains one or more values that are - /// equal to \a value, and if there are conflicts, it calls - /// Table::merge_rows() for the row_ndx to be replaced by the - /// existing row, followed by a Table::move_last_over() of row_ndx. The - /// return value is always a row index of a row that contains \a value in - /// the specified column, possibly different from \a row_ndx if a conflict - /// occurred. Users intending to implement primary keys must therefore - /// manually check for duplicates if they want to raise an error instead. - /// - /// NOTE: It is an error to call either function after adding elements to a - /// linklist in the object. In general, calling set_int_unique() or - /// set_string_unique() or set_null_unique() should be the first thing that - /// happens after creating a row. These limitations are imposed by limitations - /// in the Realm Object Server and may be relaxed in the future. A violation of - /// these rules results in a LogicError being thrown. - /// - /// add_int() adds a 64-bit signed integer to the current value of the - /// cell. If the addition would cause signed integer overflow or - /// underflow, the addition "wraps around" with semantics similar to - /// unsigned integer arithmetic, such that Table::max_integer + 1 == - /// Table::min_integer and Table::min_integer - 1 == Table::max_integer. - /// Note that the wrapping is platform-independent (all platforms wrap in - /// the same way regardless of integer representation). If the existing - /// value in the cell is null, a LogicError exception is thrown. - /// - /// insert_substring() inserts the specified string into the currently - /// stored string at the specified position. The position must be less than - /// or equal to the size of the currently stored string. - /// - /// remove_substring() removes the specified byte range from the currently - /// stored string. The beginning of the range (\a pos) must be less than or - /// equal to the size of the currently stored string. If the specified range - /// extends beyond the end of the currently stored string, it will be - /// silently clamped. - /// - /// String level modifications performed via insert_substring() and - /// remove_substring() are mergable and subject to operational - /// trsnaformation. That is, the effect of two causally unrelated - /// modifications will in general both be retained during synchronization. - - static const size_t max_string_size = 0xFFFFF8 - Array::header_size - 1; - static const size_t max_binary_size = 0xFFFFF8 - Array::header_size; - - // FIXME: These limits should be chosen independently of the underlying - // platform's choice to define int64_t and independent of the integer - // representation. The current values only work for 2's complement, which is - // not guaranteed by the standard. - static constexpr int_fast64_t max_integer = std::numeric_limits::max(); - static constexpr int_fast64_t min_integer = std::numeric_limits::min(); - - void set_int(size_t column_ndx, size_t row_ndx, int_fast64_t value, bool is_default = false); - size_t set_int_unique(size_t column_ndx, size_t row_ndx, int_fast64_t value); - void set_bool(size_t column_ndx, size_t row_ndx, bool value, bool is_default = false); - void set_olddatetime(size_t column_ndx, size_t row_ndx, OldDateTime value, bool is_default = false); - void set_timestamp(size_t column_ndx, size_t row_ndx, Timestamp value, bool is_default = false); - template - void set_enum(size_t column_ndx, size_t row_ndx, E value); - void set_float(size_t column_ndx, size_t row_ndx, float value, bool is_default = false); - void set_double(size_t column_ndx, size_t row_ndx, double value, bool is_default = false); - void set_string(size_t column_ndx, size_t row_ndx, StringData value, bool is_default = false); - size_t set_string_unique(size_t column_ndx, size_t row_ndx, StringData value); - void set_binary(size_t column_ndx, size_t row_ndx, BinaryData value, bool is_default = false); - void set_mixed(size_t column_ndx, size_t row_ndx, Mixed value, bool is_default = false); - void set_link(size_t column_ndx, size_t row_ndx, size_t target_row_ndx, bool is_default = false); - void nullify_link(size_t column_ndx, size_t row_ndx); - void set_null(size_t column_ndx, size_t row_ndx, bool is_default = false); - void set_null_unique(size_t col_ndx, size_t row_ndx); - - void add_int(size_t column_ndx, size_t row_ndx, int_fast64_t value); - - void insert_substring(size_t col_ndx, size_t row_ndx, size_t pos, StringData); - void remove_substring(size_t col_ndx, size_t row_ndx, size_t pos, size_t substring_size = realm::npos); - - //@} - - /// Assumes that the specified column is a subtable column (in - /// particular, not a mixed column) and that the specified table - /// has a spec that is compatible with that column, that is, the - /// number of columns must be the same, and corresponding columns - /// must have identical data types (as returned by - /// get_column_type()). - void set_subtable(size_t col_ndx, size_t row_ndx, const Table*); - void set_mixed_subtable(size_t col_ndx, size_t row_ndx, const Table*); - - - // Sub-tables (works on columns whose type is either 'subtable' or - // 'mixed', for a value in a mixed column that is not a subtable, - // get_subtable() returns null, get_subtable_size() returns zero, - // and clear_subtable() replaces the value with an empty table.) - TableRef get_subtable(size_t column_ndx, size_t row_ndx); - ConstTableRef get_subtable(size_t column_ndx, size_t row_ndx) const; - size_t get_subtable_size(size_t column_ndx, size_t row_ndx) const noexcept; - void clear_subtable(size_t column_ndx, size_t row_ndx); - - // Backlinks - size_t get_backlink_count(size_t row_ndx, const Table& origin, size_t origin_col_ndx) const noexcept; - size_t get_backlink(size_t row_ndx, const Table& origin, size_t origin_col_ndx, size_t backlink_ndx) const - noexcept; - - - //@{ - - /// If this accessor is attached to a subtable, then that subtable has a - /// parent table, and the subtable either resides in a column of type - /// `table` or of type `mixed` in that parent. In that case - /// get_parent_table() returns a reference to the accessor associated with - /// the parent, and get_parent_row_index() returns the index of the row in - /// which the subtable resides. In all other cases (free-standing and - /// group-level tables), get_parent_table() returns null and - /// get_parent_row_index() returns realm::npos. - /// - /// If this accessor is attached to a subtable, and \a column_ndx_out is - /// specified, then `*column_ndx_out` is set to the index of the column of - /// the parent table in which the subtable resides. If this accessor is not - /// attached to a subtable, then `*column_ndx_out` will retain its original - /// value upon return. - - TableRef get_parent_table(size_t* column_ndx_out = nullptr) noexcept; - ConstTableRef get_parent_table(size_t* column_ndx_out = nullptr) const noexcept; - size_t get_parent_row_index() const noexcept; - - //@} - - - /// Only group-level unordered tables can be used as origins or targets of - /// links. - bool is_group_level() const noexcept; - - /// If this table is a group-level table, then this function returns the - /// index of this table within the group. Otherwise it returns realm::npos. - size_t get_index_in_group() const noexcept; - - // Aggregate functions - size_t count_int(size_t column_ndx, int64_t value) const; - size_t count_string(size_t column_ndx, StringData value) const; - size_t count_float(size_t column_ndx, float value) const; - size_t count_double(size_t column_ndx, double value) const; - - int64_t sum_int(size_t column_ndx) const; - double sum_float(size_t column_ndx) const; - double sum_double(size_t column_ndx) const; - int64_t maximum_int(size_t column_ndx, size_t* return_ndx = nullptr) const; - float maximum_float(size_t column_ndx, size_t* return_ndx = nullptr) const; - double maximum_double(size_t column_ndx, size_t* return_ndx = nullptr) const; - OldDateTime maximum_olddatetime(size_t column_ndx, size_t* return_ndx = nullptr) const; - Timestamp maximum_timestamp(size_t column_ndx, size_t* return_ndx = nullptr) const; - int64_t minimum_int(size_t column_ndx, size_t* return_ndx = nullptr) const; - float minimum_float(size_t column_ndx, size_t* return_ndx = nullptr) const; - double minimum_double(size_t column_ndx, size_t* return_ndx = nullptr) const; - OldDateTime minimum_olddatetime(size_t column_ndx, size_t* return_ndx = nullptr) const; - Timestamp minimum_timestamp(size_t column_ndx, size_t* return_ndx = nullptr) const; - double average_int(size_t column_ndx, size_t* value_count = nullptr) const; - double average_float(size_t column_ndx, size_t* value_count = nullptr) const; - double average_double(size_t column_ndx, size_t* value_count = nullptr) const; - - // Searching - size_t find_first_link(size_t target_row_index) const; - size_t find_first_int(size_t column_ndx, int64_t value) const; - size_t find_first_bool(size_t column_ndx, bool value) const; - size_t find_first_olddatetime(size_t column_ndx, OldDateTime value) const; - size_t find_first_timestamp(size_t column_ndx, Timestamp value) const; - size_t find_first_float(size_t column_ndx, float value) const; - size_t find_first_double(size_t column_ndx, double value) const; - size_t find_first_string(size_t column_ndx, StringData value) const; - size_t find_first_binary(size_t column_ndx, BinaryData value) const; - size_t find_first_null(size_t column_ndx) const; - - TableView find_all_link(size_t target_row_index); - ConstTableView find_all_link(size_t target_row_index) const; - TableView find_all_int(size_t column_ndx, int64_t value); - ConstTableView find_all_int(size_t column_ndx, int64_t value) const; - TableView find_all_bool(size_t column_ndx, bool value); - ConstTableView find_all_bool(size_t column_ndx, bool value) const; - TableView find_all_olddatetime(size_t column_ndx, OldDateTime value); - ConstTableView find_all_olddatetime(size_t column_ndx, OldDateTime value) const; - TableView find_all_float(size_t column_ndx, float value); - ConstTableView find_all_float(size_t column_ndx, float value) const; - TableView find_all_double(size_t column_ndx, double value); - ConstTableView find_all_double(size_t column_ndx, double value) const; - TableView find_all_string(size_t column_ndx, StringData value); - ConstTableView find_all_string(size_t column_ndx, StringData value) const; - TableView find_all_binary(size_t column_ndx, BinaryData value); - ConstTableView find_all_binary(size_t column_ndx, BinaryData value) const; - TableView find_all_null(size_t column_ndx); - ConstTableView find_all_null(size_t column_ndx) const; - - /// The following column types are supported: String, Integer, OldDateTime, Bool - TableView get_distinct_view(size_t column_ndx); - ConstTableView get_distinct_view(size_t column_ndx) const; - - TableView get_sorted_view(size_t column_ndx, bool ascending = true); - ConstTableView get_sorted_view(size_t column_ndx, bool ascending = true) const; - - TableView get_sorted_view(SortDescriptor order); - ConstTableView get_sorted_view(SortDescriptor order) const; - - TableView get_range_view(size_t begin, size_t end); - ConstTableView get_range_view(size_t begin, size_t end) const; - - TableView get_backlink_view(size_t row_ndx, Table* src_table, size_t src_col_ndx); - - - // Pivot / aggregate operation types. Experimental! Please do not document method publicly. - enum AggrType { - aggr_count, - aggr_sum, - aggr_avg, - aggr_min, - aggr_max, - }; - - // Simple pivot aggregate method. Experimental! Please do not document method publicly. - void aggregate(size_t group_by_column, size_t aggr_column, AggrType op, Table& result, - const IntegerColumn* viewrefs = nullptr) const; - - /// Report the current versioning counter for the table. The versioning counter is guaranteed to - /// change when the contents of the table changes after advance_read() or promote_to_write(), or - /// immediately after calls to methods which change the table. The term "change" means "change of - /// value": The storage layout of the table may change, for example due to optimization, but this - /// is not considered a change of a value. This means that you *cannot* use a non-changing version - /// count to indicate that object addresses (e.g. strings, binary data) remain the same. - /// The versioning counter *may* change (but is not required to do so) when another table linked - /// from this table, or linking to this table, is changed. The version counter *may* also change - /// without any apparent reason. - uint_fast64_t get_version_counter() const noexcept; - -private: - template - size_t find_first(size_t column_ndx, T value) const; // called by above methods - template - TableView find_all(size_t column_ndx, T value); - -public: - //@{ - /// Find the lower/upper bound according to a column that is - /// already sorted in ascending order. - /// - /// For an integer column at index 0, and an integer value '`v`', - /// lower_bound_int(0,v) returns the index '`l`' of the first row - /// such that `get_int(0,l) ≥ v`, and upper_bound_int(0,v) - /// returns the index '`u`' of the first row such that - /// `get_int(0,u) > v`. In both cases, if no such row is found, - /// the returned value is the number of rows in the table. - /// - /// 3 3 3 4 4 4 5 6 7 9 9 9 - /// ^ ^ ^ ^ ^ - /// | | | | | - /// | | | | -- Lower and upper bound of 15 - /// | | | | - /// | | | -- Lower and upper bound of 8 - /// | | | - /// | | -- Upper bound of 4 - /// | | - /// | -- Lower bound of 4 - /// | - /// -- Lower and upper bound of 1 - /// - /// These functions are similar to std::lower_bound() and - /// std::upper_bound(). - /// - /// The string versions assume that the column is sorted according - /// to StringData::operator<(). - size_t lower_bound_int(size_t column_ndx, int64_t value) const noexcept; - size_t upper_bound_int(size_t column_ndx, int64_t value) const noexcept; - size_t lower_bound_bool(size_t column_ndx, bool value) const noexcept; - size_t upper_bound_bool(size_t column_ndx, bool value) const noexcept; - size_t lower_bound_float(size_t column_ndx, float value) const noexcept; - size_t upper_bound_float(size_t column_ndx, float value) const noexcept; - size_t lower_bound_double(size_t column_ndx, double value) const noexcept; - size_t upper_bound_double(size_t column_ndx, double value) const noexcept; - size_t lower_bound_string(size_t column_ndx, StringData value) const noexcept; - size_t upper_bound_string(size_t column_ndx, StringData value) const noexcept; - //@} - - // Queries - // Using where(tv) is the new method to perform queries on TableView. The 'tv' can have any order; it does not - // need to be sorted, and, resulting view retains its order. - Query where(TableViewBase* tv = nullptr) - { - return Query(*this, tv); - } - - // FIXME: We need a ConstQuery class or runtime check against modifications in read transaction. - Query where(TableViewBase* tv = nullptr) const - { - return Query(*this, tv); - } - - // Perform queries on a LinkView. The returned Query holds a reference to lv. - Query where(const LinkViewRef& lv) - { - return Query(*this, lv); - } - - Table& link(size_t link_column); - Table& backlink(const Table& origin, size_t origin_col_ndx); - - // Optimizing. enforce == true will enforce enumeration of all string columns; - // enforce == false will auto-evaluate if they should be enumerated or not - void optimize(bool enforce = false); - - /// Write this table (or a slice of this table) to the specified - /// output stream. - /// - /// The output will have the same format as any other Realm - /// database file, such as those produced by Group::write(). In - /// this case, however, the resulting database file will contain - /// exactly one table, and that table will contain only the - /// specified slice of the source table (this table). - /// - /// The new table will always have the same dynamic type (see - /// Descriptor) as the source table (this table), and unless it is - /// overridden (\a override_table_name), the new table will have - /// the same name as the source table (see get_name()). Indexes - /// (see add_search_index()) will not be carried over to the new - /// table. - /// - /// \param out The destination output stream buffer. - /// - /// \param offset Index of first row to include (if `slice_size > - /// 0`). Must be less than, or equal to size(). - /// - /// \param slice_size Number of rows to include. May be zero. If - /// `slice_size > size() - offset`, then the effective size of - /// the written slice will be `size() - offset`. - /// - /// \param override_table_name Custom name to write out instead of - /// the actual table name. - /// - /// \throw std::out_of_range If `offset > size()`. - /// - /// FIXME: While this function does provided a maximally efficient - /// way of serializing part of a table, it offers little in terms - /// of general utility. This is unfortunate, because it pulls - /// quite a large amount of code into the core library to support - /// it. - void write(std::ostream& out, size_t offset = 0, size_t slice_size = npos, - StringData override_table_name = StringData()) const; - - // Conversion - void to_json(std::ostream& out, size_t link_depth = 0, - std::map* renames = nullptr) const; - void to_string(std::ostream& out, size_t limit = 500) const; - void row_to_string(size_t row_ndx, std::ostream& out) const; - - // Get a reference to this table - TableRef get_table_ref() - { - return TableRef(this); - } - ConstTableRef get_table_ref() const - { - return ConstTableRef(this); - } - - /// \brief Compare two tables for equality. - /// - /// Two tables are equal if they have equal descriptors - /// (`Descriptor::operator==()`) and equal contents. Equal descriptors imply - /// that the two tables have the same columns in the same order. Equal - /// contents means that the two tables must have the same number of rows, - /// and that for each row index, the two rows must have the same values in - /// each column. - /// - /// In mixed columns, both the value types and the values are required to be - /// equal. - /// - /// For a particular row and column, if the two values are themselves tables - /// (subtable and mixed columns) value equality implies a recursive - /// invocation of `Table::operator==()`. - bool operator==(const Table&) const; - - /// \brief Compare two tables for inequality. - /// - /// See operator==(). - bool operator!=(const Table& t) const; - - /// A subtable in a column of type 'table' (which shares descriptor with - /// other subtables in the same column) is initially in a degenerate state - /// where it takes up a minimal amout of space. This function returns true - /// if, and only if the table accessor is attached to such a subtable. This - /// function is mainly intended for debugging purposes. - bool is_degenerate() const noexcept; - - // Debug - void verify() const; -#ifdef REALM_DEBUG - void to_dot(std::ostream&, StringData title = StringData()) const; - void print() const; - MemStats stats() const; - void dump_node_structure() const; // To std::cerr (for GDB) - void dump_node_structure(std::ostream&, int level) const; -#endif - - class Parent; - using HandoverPatch = TableHandoverPatch; - static void generate_patch(const Table* ref, std::unique_ptr& patch); - static TableRef create_from_and_consume_patch(std::unique_ptr& patch, Group& group); - -protected: - /// Get a pointer to the accessor of the specified subtable. The - /// accessor will be created if it does not already exist. - /// - /// The returned table pointer must **always** end up being - /// wrapped in some instantiation of BasicTableRef<>. - Table* get_subtable_ptr(size_t col_ndx, size_t row_ndx); - - /// See non-const get_subtable_ptr(). - const Table* get_subtable_ptr(size_t col_ndx, size_t row_ndx) const; - - /// Compare the rows of two tables under the assumption that the two tables - /// have the same number of columns, and the same data type at each column - /// index (as expressed through the DataType enum). - bool compare_rows(const Table&) const; - - void set_into_mixed(Table* parent, size_t col_ndx, size_t row_ndx) const; - - void check_lists_are_empty(size_t row_ndx) const; - -private: - class SliceWriter; - - // Number of rows in this table - size_t m_size; - - // Underlying array structure. `m_top` is in use only for root tables; that - // is, for tables with independent descriptor. `m_columns` contains a ref - // for each column and search index in order of the columns. A search index - // ref always occurs immediately after the ref of the column to which the - // search index belongs. - // - // A subtable column (a column of type `type_table`) is essentially just a - // column of 'refs' pointing to the root node of each subtable. - // - // To save space in the database file, a subtable in such a column always - // starts out in a degenerate form where nothing is allocated on its behalf, - // and a null 'ref' is stored in the corresponding slot of the column. A - // subtable remains in this degenerate state until the first row is added to - // the subtable. - // - // For this scheme to work, it must be (and is) possible to create a table - // accessor that refers to a degenerate subtable. A table accessor (instance - // of `Table`) refers to a degenerate subtable if, and only if `m_columns` - // is unattached. - // - // FIXME: The fact that `m_columns` may be detached means that many - // functions (even non-modifying functions) need to check for that before - // accessing the contents of the table. This incurs a runtime - // overhead. Consider whether this overhead can be eliminated by having - // `Table::m_columns` always attached to something, and then detect the - // degenerate state in a different way. - Array m_top; - Array m_columns; // 2nd slot in m_top (for root tables) - Spec m_spec; // 1st slot in m_top (for root tables) - - // Is guaranteed to be empty for a detached accessor. Otherwise it is empty - // when the table accessor is attached to a degenerate subtable (unattached - // `m_columns`), otherwise it contains precisely one column accessor for - // each column in the table, in order. - // - // In some cases an entry may be null. This is currently possible only in - // connection with Group::advance_transact(), but it means that several - // member functions must be prepared to handle these null entries; in - // particular, detach(), ~Table(), functions called on behalf of detach() - // and ~Table(), and functiones called on behalf of - // Group::advance_transact(). - typedef std::vector column_accessors; - column_accessors m_cols; - - mutable std::atomic m_ref_count; - - // If this table is a root table (has independent descriptor), - // then Table::m_descriptor refers to the accessor of its - // descriptor when, and only when the descriptor accessor - // exists. This is used to ensure that at most one descriptor - // accessor exists for each underlying descriptor at any given - // point in time. Subdescriptors are kept unique by means of a - // registry in the parent descriptor. Table::m_descriptor is - // always null for tables with shared descriptor. - mutable std::weak_ptr m_descriptor; - - // Table view instances - // Access needs to be protected by m_accessor_mutex - typedef std::vector views; - mutable views m_views; - - // Points to first bound row accessor, or is null if there are none. - mutable RowBase* m_row_accessors = nullptr; - - // Mutex which must be locked any time the row accessor chain or m_views is used - mutable util::Mutex m_accessor_mutex; - - // Used for queries: Items are added with link() method during buildup of query - mutable std::vector m_link_chain; - - /// Used only in connection with Group::advance_transact() and - /// Table::refresh_accessor_tree(). - mutable bool m_mark; - - mutable uint_fast64_t m_version; - - void erase_row(size_t row_ndx, bool is_move_last_over); - void batch_erase_rows(const IntegerColumn& row_indexes, bool is_move_last_over); - void do_remove(size_t row_ndx, bool broken_reciprocal_backlinks); - void do_move_last_over(size_t row_ndx, bool broken_reciprocal_backlinks); - void do_swap_rows(size_t row_ndx_1, size_t row_ndx_2); - void do_merge_rows(size_t row_ndx, size_t new_row_ndx); - void do_clear(bool broken_reciprocal_backlinks); - size_t do_set_link(size_t col_ndx, size_t row_ndx, size_t target_row_ndx); - template - size_t do_find_unique(ColType& col, size_t ndx, T&& value, bool& conflict); - template - size_t do_set_unique_null(ColType& col, size_t ndx, bool& conflict); - template - size_t do_set_unique(ColType& column, size_t row_ndx, T&& value, bool& conflict); - - void upgrade_file_format(size_t target_file_format_version); - - // Upgrades OldDateTime columns to Timestamp columns - void upgrade_olddatetime(); - - /// Update the version of this table and all tables which have links to it. - /// This causes all views referring to those tables to go out of sync, so that - /// calls to sync_if_needed() will bring the view up to date by reexecuting the - /// query. - /// - /// \param bump_global chooses whether the global versioning counter must be - /// bumped first as part of the update. This is the normal mode of operation, - /// when a change is made to the table. When calling recursively (following links - /// or going to the parent table), the parameter should be set to false to correctly - /// prune traversal. - void bump_version(bool bump_global = true) const noexcept; - - /// Disable copying assignment. - /// - /// It could easily be implemented by calling assign(), but the - /// non-checking nature of the low-level dynamically typed API - /// makes it too risky to offer this feature as an - /// operator. - /// - /// FIXME: assign() has not yet been implemented, but the - /// intention is that it will copy the rows of the argument table - /// into this table after clearing the original contents, and for - /// target tables without a shared spec, it would also copy the - /// spec. For target tables with shared spec, it would be an error - /// to pass an argument table with an incompatible spec, but - /// assign() would not check for spec compatibility. This would - /// make it ideal as a basis for implementing operator=() for - /// typed tables. - Table& operator=(const Table&); - - /// Used when constructing an accessor whose lifetime is going to be managed - /// by reference counting. The lifetime of accessors of free-standing tables - /// allocated on the stack by the application is not managed by reference - /// counting, so that is a case where this tag must **not** be specified. - class ref_count_tag { - }; - - /// Create an uninitialized accessor whose lifetime is managed by reference - /// counting. - Table(ref_count_tag, Allocator&); - - void init(ref_type top_ref, ArrayParent*, size_t ndx_in_parent, bool skip_create_column_accessors = false); - void init(ConstSubspecRef shared_spec, ArrayParent* parent_column, size_t parent_row_ndx); - - static void do_insert_column(Descriptor&, size_t col_ndx, DataType type, StringData name, - LinkTargetInfo& link_target_info, bool nullable = false); - static void do_insert_column_unless_exists(Descriptor&, size_t col_ndx, DataType type, StringData name, - LinkTargetInfo& link, bool nullable = false, - bool* was_inserted = nullptr); - static void do_erase_column(Descriptor&, size_t col_ndx); - static void do_rename_column(Descriptor&, size_t col_ndx, StringData name); - static void do_move_column(Descriptor&, size_t col_ndx_1, size_t col_ndx_2); - - struct InsertSubtableColumns; - struct EraseSubtableColumns; - struct RenameSubtableColumns; - struct MoveSubtableColumns; - - void insert_root_column(size_t col_ndx, DataType type, StringData name, LinkTargetInfo& link_target, - bool nullable = false); - void erase_root_column(size_t col_ndx); - void move_root_column(size_t from, size_t to); - void do_insert_root_column(size_t col_ndx, ColumnType, StringData name, bool nullable = false); - void do_erase_root_column(size_t col_ndx); - void do_move_root_column(size_t from, size_t to); - void do_set_link_type(size_t col_ndx, LinkType); - void insert_backlink_column(size_t origin_table_ndx, size_t origin_col_ndx, size_t backlink_col_ndx); - void erase_backlink_column(size_t origin_table_ndx, size_t origin_col_ndx); - void update_link_target_tables(size_t old_col_ndx_begin, size_t new_col_ndx_begin); - void update_link_target_tables_after_column_move(size_t moved_from, size_t moved_to); - - struct SubtableUpdater { - virtual void update(const SubtableColumn&, Array& subcolumns) = 0; - virtual void update_accessor(Table&) = 0; - virtual ~SubtableUpdater() - { - } - }; - static void update_subtables(Descriptor&, SubtableUpdater*); - void update_subtables(const size_t* col_path_begin, const size_t* col_path_end, SubtableUpdater*); - - struct AccessorUpdater { - virtual void update(Table&) = 0; - virtual void update_parent(Table&) = 0; - virtual ~AccessorUpdater() - { - } - }; - void update_accessors(const size_t* col_path_begin, const size_t* col_path_end, AccessorUpdater&); - - void create_degen_subtab_columns(); - ColumnBase* create_column_accessor(ColumnType, size_t col_ndx, size_t ndx_in_parent); - void destroy_column_accessors() noexcept; - - /// Called in the context of Group::commit() to ensure that - /// attached table accessors stay valid across a commit. Please - /// note that this works only for non-transactional commits. Table - /// accessors obtained during a transaction are always detached - /// when the transaction ends. - void update_from_parent(size_t old_baseline) noexcept; - - // Support function for conversions - void to_string_header(std::ostream& out, std::vector& widths) const; - void to_string_row(size_t row_ndx, std::ostream& out, const std::vector& widths) const; - - // recursive methods called by to_json, to follow links - void to_json(std::ostream& out, size_t link_depth, std::map& renames, - std::vector& followed) const; - void to_json_row(size_t row_ndx, std::ostream& out, size_t link_depth, - std::map& renames, std::vector& followed) const; - void to_json_row(size_t row_ndx, std::ostream& out, size_t link_depth = 0, - std::map* renames = nullptr) const; - - // Detach accessor from underlying table. Caller must ensure that - // a reference count exists upon return, for example by obtaining - // an extra reference count before the call. - // - // This function puts this table accessor into the detached - // state. This detaches it from the underlying structure of array - // nodes. It also recursively detaches accessors for subtables, - // and the type descriptor accessor. When this function returns, - // is_attached() will return false. - // - // This function may be called for a table accessor that is - // already in the detached state (idempotency). - // - // It is also valid to call this function for a table accessor - // that has not yet been detached, but whose underlying structure - // of arrays have changed in an unpredictable/unknown way. This - // kind of change generally happens when a modifying table - // operation fails, and also when one transaction is ended and a - // new one is started. - void detach() noexcept; - - /// Detach and remove all attached row, link list, and subtable - /// accessors. This function does not discard the descriptor accessor, if - /// any, and it does not discard column accessors either. - void discard_child_accessors() noexcept; - - void discard_row_accessors() noexcept; - - // Detach the type descriptor accessor if it exists. - void discard_desc_accessor() noexcept; - - void bind_ptr() const noexcept; - void unbind_ptr() const noexcept; - - void register_view(const TableViewBase* view); - void unregister_view(const TableViewBase* view) noexcept; - void move_registered_view(const TableViewBase* old_addr, const TableViewBase* new_addr) noexcept; - void discard_views() noexcept; - - void register_row_accessor(RowBase*) const noexcept; - void unregister_row_accessor(RowBase*) const noexcept; - void do_unregister_row_accessor(RowBase*) const noexcept; - - class UnbindGuard; - - ColumnType get_real_column_type(size_t column_ndx) const noexcept; - - /// If this table is a group-level table, the parent group is returned, - /// otherwise null is returned. - Group* get_parent_group() const noexcept; - - const ColumnBase& get_column_base(size_t column_ndx) const noexcept; - ColumnBase& get_column_base(size_t column_ndx); - - const ColumnBaseWithIndex& get_column_base_indexed(size_t ndx) const noexcept; - ColumnBaseWithIndex& get_column_base_indexed(size_t ndx); - - template - T& get_column(size_t ndx); - - template - const T& get_column(size_t ndx) const noexcept; - - IntegerColumn& get_column(size_t column_ndx); - const IntegerColumn& get_column(size_t column_ndx) const noexcept; - IntNullColumn& get_column_int_null(size_t column_ndx); - const IntNullColumn& get_column_int_null(size_t column_ndx) const noexcept; - FloatColumn& get_column_float(size_t column_ndx); - const FloatColumn& get_column_float(size_t column_ndx) const noexcept; - DoubleColumn& get_column_double(size_t column_ndx); - const DoubleColumn& get_column_double(size_t column_ndx) const noexcept; - StringColumn& get_column_string(size_t column_ndx); - const StringColumn& get_column_string(size_t column_ndx) const noexcept; - BinaryColumn& get_column_binary(size_t column_ndx); - const BinaryColumn& get_column_binary(size_t column_ndx) const noexcept; - StringEnumColumn& get_column_string_enum(size_t column_ndx); - const StringEnumColumn& get_column_string_enum(size_t column_ndx) const noexcept; - SubtableColumn& get_column_table(size_t column_ndx); - const SubtableColumn& get_column_table(size_t column_ndx) const noexcept; - MixedColumn& get_column_mixed(size_t column_ndx); - const MixedColumn& get_column_mixed(size_t column_ndx) const noexcept; - TimestampColumn& get_column_timestamp(size_t column_ndx); - const TimestampColumn& get_column_timestamp(size_t column_ndx) const noexcept; - const LinkColumnBase& get_column_link_base(size_t ndx) const noexcept; - LinkColumnBase& get_column_link_base(size_t ndx); - const LinkColumn& get_column_link(size_t ndx) const noexcept; - LinkColumn& get_column_link(size_t ndx); - const LinkListColumn& get_column_link_list(size_t ndx) const noexcept; - LinkListColumn& get_column_link_list(size_t ndx); - const BacklinkColumn& get_column_backlink(size_t ndx) const noexcept; - BacklinkColumn& get_column_backlink(size_t ndx); - - void instantiate_before_change(); - void validate_column_type(const ColumnBase& col, ColumnType expected_type, size_t ndx) const; - - static size_t get_size_from_ref(ref_type top_ref, Allocator&) noexcept; - static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator&) noexcept; - - const Table* get_parent_table_ptr(size_t* column_ndx_out = nullptr) const noexcept; - Table* get_parent_table_ptr(size_t* column_ndx_out = nullptr) noexcept; - - /// Create an empty table with independent spec and return just - /// the reference to the underlying memory. - static ref_type create_empty_table(Allocator&); - - /// Create a column of the specified type, fill it with the - /// specified number of default values, and return just the - /// reference to the underlying memory. - static ref_type create_column(ColumnType column_type, size_t num_default_values, bool nullable, Allocator&); - - /// Construct a copy of the columns array of this table using the - /// specified allocator and return just the ref to that array. - /// - /// In the clone, no string column will be of the enumeration - /// type. - ref_type clone_columns(Allocator&) const; - - /// Construct a complete copy of this table (including its spec) - /// using the specified allocator and return just the ref to the - /// new top array. - ref_type clone(Allocator&) const; - - /// True for `col_type_Link` and `col_type_LinkList`. - static bool is_link_type(ColumnType) noexcept; - - void connect_opposite_link_columns(size_t link_col_ndx, Table& target_table, size_t backlink_col_ndx) noexcept; - - size_t get_num_strong_backlinks(size_t row_ndx) const noexcept; - - //@{ - - /// Cascading removal of strong links. - /// - /// cascade_break_backlinks_to() removes all backlinks pointing to the row - /// at \a row_ndx. Additionally, if this causes the number of **strong** - /// backlinks originating from a particular opposite row (target row of - /// corresponding forward link) to drop to zero, and that row is not already - /// in \a state.rows, then that row is added to \a state.rows, and - /// cascade_break_backlinks_to() is called recursively for it. This - /// operation is the first half of the cascading row removal operation. The - /// second half is performed by passing the resulting contents of \a - /// state.rows to remove_backlink_broken_rows(). - /// - /// Operations that trigger cascading row removal due to explicit removal of - /// one or more rows (the *initiating rows*), should add those rows to \a - /// rows initially, and then call cascade_break_backlinks_to() once for each - /// of them in turn. This is opposed to carrying out the explicit row - /// removals independently, which is also possible, but does require that - /// any initiating rows, that end up in \a state.rows due to link cycles, - /// are removed before passing \a state.rows to - /// remove_backlink_broken_rows(). In the case of clear(), where all rows of - /// a table are explicitly removed, it is better to use - /// cascade_break_backlinks_to_all_rows(), and then carry out the table - /// clearing as an independent step. For operations that trigger cascading - /// row removal for other reasons than explicit row removal, \a state.rows - /// must be empty initially, but cascade_break_backlinks_to() must still be - /// called for each of the initiating rows. - /// - /// When the last non-recursive invocation of cascade_break_backlinks_to() - /// returns, all forward links originating from a row in \a state.rows have - /// had their reciprocal backlinks removed, so remove_backlink_broken_rows() - /// does not perform reciprocal backlink removal at all. Additionally, all - /// remaining backlinks originating from rows in \a state.rows are - /// guaranteed to point to rows that are **not** in \a state.rows. This is - /// true because any backlink that was pointing to a row in \a state.rows - /// has been removed by one of the invocations of - /// cascade_break_backlinks_to(). The set of forward links, that correspond - /// to these remaining backlinks, is precisely the set of forward links that - /// need to be removed/nullified by remove_backlink_broken_rows(), which it - /// does by way of reciprocal forward link removal. Note also, that while - /// all the rows in \a state.rows can have remaining **weak** backlinks - /// originating from them, only the initiating rows in \a state.rows can - /// have remaining **strong** backlinks originating from them. This is true - /// because a non-initiating row is added to \a state.rows only when the - /// last backlink originating from it is lost. - /// - /// Each row removal is replicated individually (as opposed to one - /// replication instruction for the entire cascading operation). This is - /// done because it provides an easy way for Group::advance_transact() to - /// know which tables are affected by the cascade. Note that this has - /// several important consequences: First of all, the replication log - /// receiver must execute the row removal instructions in a non-cascading - /// fashion, meaning that there will be an asymmetry between the two sides - /// in how the effect of the cascade is brought about. While this is fine - /// for simple 1-to-1 replication, it may end up interfering badly with - /// *transaction merging*, when that feature is introduced. Imagine for - /// example that the cascade initiating operation gets canceled during - /// conflict resolution, but some, or all of the induced row removals get to - /// stay. That would break causal consistency. It is important, however, for - /// transaction merging that the cascaded row removals are explicitly - /// mentioned in the replication log, such that they can be used to adjust - /// row indexes during the *operational transform*. - /// - /// cascade_break_backlinks_to_all_rows() has the same affect as calling - /// cascade_break_backlinks_to() once for each row in the table. When - /// calling this function, \a state.stop_on_table must be set to the origin - /// table (origin table of corresponding forward links), and \a - /// state.stop_on_link_list_column must be null. - /// - /// It is immaterial which table remove_backlink_broken_rows() is called on, - /// as long it that table is in the same group as the removed rows. - - void cascade_break_backlinks_to(size_t row_ndx, CascadeState& state); - void cascade_break_backlinks_to_all_rows(CascadeState& state); - void remove_backlink_broken_rows(const CascadeState&); - - //@} - - /// Used by query. Follows chain of link columns and returns final target table - const Table* get_link_chain_target(const std::vector& link_chain) const; - - /// Remove the specified row by the 'move last over' method. - void do_move_last_over(size_t row_ndx); - - // Precondition: 1 <= end - begin - size_t* record_subtable_path(size_t* begin, size_t* end) const noexcept; - - /// Check if an accessor exists for the specified subtable. If it does, - /// return a pointer to it, otherwise return null. This function assumes - /// that the specified column index in a valid index into `m_cols` but does - /// not otherwise assume more than minimal accessor consistency (see - /// AccessorConsistencyLevels.) - Table* get_subtable_accessor(size_t col_ndx, size_t row_ndx) noexcept; - - /// Unless the column accessor is missing, this function returns the - /// accessor for the target table of the specified link-type column. The - /// column accessor is said to be missing if `m_cols[col_ndx]` is null, and - /// this can happen only during certain operations such as the updating of - /// the accessor tree when a read transaction is advanced. Note that for - /// link type columns, the target table accessor exists when, and only when - /// the origin table accessor exists. This function assumes that the - /// specified column index in a valid index into `m_cols` and that the - /// column is a link-type column. Beyond that, it assume nothing more than - /// minimal accessor consistency (see AccessorConsistencyLevels.) - Table* get_link_target_table_accessor(size_t col_ndx) noexcept; - - void discard_subtable_accessor(size_t col_ndx, size_t row_ndx) noexcept; - - void adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept; - void adj_acc_erase_row(size_t row_ndx) noexcept; - void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; - - /// Adjust this table accessor and its subordinates after move_last_over() - /// (or its inverse). - /// - /// First, any row, subtable, or link list accessors registered as being at - /// \a to_row_ndx will be detached, as that row is assumed to have been - /// replaced. Next, any row, subtable, or link list accessors registered as - /// being at \a from_row_ndx, will be reregistered as being at \a - /// to_row_ndx, as the row at \a from_row_ndx is assumed to have been moved - /// to \a to_row_ndx. - /// - /// Crucially, if \a to_row_ndx is equal to \a from_row_ndx, then row, - /// subtable, or link list accessors at that row are **still detached**. - /// - /// Additionally, this function causes all link-adjacent tables to be marked - /// (dirty). Two tables are link-adjacent if one is the target table of a - /// link column of the other table. Note that this marking follows these - /// relations in both directions, but only to a depth of one. - /// - /// When this function is used in connection with move_last_over(), set \a - /// to_row_ndx to the index of the row to be removed, and set \a - /// from_row_ndx to the index of the last row in the table. As mentioned - /// earlier, this function can also be used in connection with the **inverse - /// of** move_last_over(), which is an operation that vacates a row by - /// moving its contents into a new last row of the table. In that case, set - /// \a to_row_ndx to one plus the index of the last row in the table, and - /// set \a from_row_ndx to the index of the row to be vacated. - /// - /// This function is used as part of Table::refresh_accessor_tree() to - /// promote the state of the accessors from Minimal Consistency into - /// Structural Correspondence, so it must be able to execute without - /// accessing the underlying array nodes. - void adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; - - void adj_acc_clear_root_table() noexcept; - void adj_acc_clear_nonroot_table() noexcept; - void adj_row_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept; - void adj_row_acc_erase_row(size_t row_ndx) noexcept; - void adj_row_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - void adj_row_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; - - /// Called by adj_acc_move_over() to adjust row accessors. - void adj_row_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; - - void adj_insert_column(size_t col_ndx); - void adj_erase_column(size_t col_ndx) noexcept; - void adj_move_column(size_t col_ndx_1, size_t col_ndx_2) noexcept; - - bool is_marked() const noexcept; - void mark() noexcept; - void unmark() noexcept; - void recursive_mark() noexcept; - void mark_link_target_tables(size_t col_ndx_begin) noexcept; - void mark_opposite_link_tables() noexcept; - - Replication* get_repl() noexcept; - - void set_ndx_in_parent(size_t ndx_in_parent) noexcept; - - /// Refresh the part of the accessor tree that is rooted at this - /// table. Subtable accessors will be refreshed only if they are marked - /// (Table::m_mark), and this applies recursively to subtables of - /// subtables. All refreshed table accessors (including this one) will be - /// unmarked upon return. - /// - /// The following conditions are necessary and sufficient for the proper - /// operation of this function: - /// - /// - This table must be a group-level table, or a subtable. It must not be - /// a free-standing table (because a free-standing table has no parent). - /// - /// - The `index in parent` property is correct. The `index in parent` - /// property of the table is the `index in parent` property of - /// `m_columns` for subtables with shared descriptor, and the `index in - /// parent` property of `m_top` for all other tables. - /// - /// - If this table has shared descriptor, then the `index in parent` - /// property of the contained spec accessor is correct. - /// - /// - The parent accessor is in a valid state (already refreshed). If the - /// parent is a group, then the group accessor (excluding its table - /// accessors) must be in a valid state. If the parent is a table, then - /// the table accessor (excluding its subtable accessors) must be in a - /// valid state. - /// - /// - Every descendant subtable accessor is marked if it needs to be - /// refreshed, or if it has a descendant accessor that needs to be - /// refreshed. - /// - /// - This table accessor, as well as all its descendant accessors, are in - /// structural correspondence with the underlying node hierarchy whose - /// root ref is stored in the parent (see AccessorConsistencyLevels). - void refresh_accessor_tree(); - - void refresh_column_accessors(size_t col_ndx_begin = 0); - - // Look for link columns starting from col_ndx_begin. - // If a link column is found, follow the link and update it's - // backlink column accessor if it is in different table. - void refresh_link_target_accessors(size_t col_ndx_begin = 0); - - bool is_cross_table_link_target() const noexcept; - -#ifdef REALM_DEBUG - void to_dot_internal(std::ostream&) const; -#endif - - friend class SubtableNode; - friend class _impl::TableFriend; - friend class Query; - template - friend class util::bind_ptr; - template - friend class SimpleQuerySupport; - friend class LangBindHelper; - friend class TableViewBase; - template - friend class Columns; - friend class Columns; - friend class ParentNode; - template - friend class SequentialGetter; - friend class RowBase; - friend class LinksToNode; - friend class LinkMap; - friend class LinkView; - friend class Group; -}; - - -class Table::Parent : public ArrayParent { -public: - ~Parent() noexcept override - { - } - -protected: - virtual StringData get_child_name(size_t child_ndx) const noexcept; - - /// If children are group-level tables, then this function returns the - /// group. Otherwise it returns null. - virtual Group* get_parent_group() noexcept; - - /// If children are subtables, then this function returns the - /// parent table. Otherwise it returns null. - /// - /// If \a column_ndx_out is not null, this function must assign the index of - /// the column within the parent table to `*column_ndx_out` when , and only - /// when this table parent is a column in a parent table. - virtual Table* get_parent_table(size_t* column_ndx_out = nullptr) noexcept; - - /// Must be called whenever a child table accessor is about to be destroyed. - /// - /// Note that the argument is a pointer to the child Table rather than its - /// `ndx_in_parent` property. This is because only minimal accessor - /// consistency can be assumed by this function. - virtual void child_accessor_destroyed(Table* child) noexcept = 0; - - virtual size_t* record_subtable_path(size_t* begin, size_t* end) noexcept; - - friend class Table; -}; - - -// Implementation: - - -inline uint_fast64_t Table::get_version_counter() const noexcept -{ - return m_version; -} - -inline void Table::bump_version(bool bump_global) const noexcept -{ - if (bump_global) { - // This is only set on initial entry through an operation on the same - // table. recursive calls (via parent or via backlinks) must be done - // with bump_global=false. - m_top.get_alloc().bump_global_version(); - } - if (m_top.get_alloc().should_propagate_version(m_version)) { - if (const Table* parent = get_parent_table_ptr()) - parent->bump_version(false); - // Recurse through linked tables, use m_mark to avoid infinite recursion - for (auto& column_ptr : m_cols) { - // We may meet a null pointer in place of a backlink column, pending - // replacement with a new one. This can happen ONLY when creation of - // the corresponding forward link column in the origin table is - // pending as well. In this case it is ok to just ignore the zeroed - // backlink column, because the origin table is guaranteed to also - // be refreshed/marked dirty and hence have it's version bumped. - if (column_ptr != nullptr) - column_ptr->bump_link_origin_table_version(); - } - } -} - -inline void Table::remove(size_t row_ndx) -{ - bool is_move_last_over = false; - erase_row(row_ndx, is_move_last_over); // Throws -} - -inline void Table::move_last_over(size_t row_ndx) -{ - bool is_move_last_over = true; - erase_row(row_ndx, is_move_last_over); // Throws -} - -inline void Table::remove_last() -{ - if (!is_empty()) - remove(size() - 1); -} - -// A good place to start if you want to understand the memory ordering -// chosen for the operations below is http://preshing.com/20130922/acquire-and-release-fences/ -inline void Table::bind_ptr() const noexcept -{ - m_ref_count.fetch_add(1, std::memory_order_relaxed); -} - -inline void Table::unbind_ptr() const noexcept -{ - // The delete operation runs the destructor, and the destructor - // must always see all changes to the object being deleted. - // Within each thread, we know that unbind_ptr will always happen after - // any changes, so it is a convenient place to do a release. - // The release will then be observed by the acquire fence in - // the case where delete is actually called (the count reaches 0) - if (m_ref_count.fetch_sub(1, std::memory_order_release) != 1) - return; - - std::atomic_thread_fence(std::memory_order_acquire); - delete this; -} - -inline void Table::register_view(const TableViewBase* view) -{ - util::LockGuard lock(m_accessor_mutex); - // Casting away constness here - operations done on tableviews - // through m_views are all internal and preserving "some" kind - // of logical constness. - m_views.push_back(const_cast(view)); -} - -inline bool Table::is_attached() const noexcept -{ - // Note that it is not possible to tie the state of attachment of a table to - // the state of attachment of m_top, because tables with shared spec do not - // have a 'top' array. Neither is it possible to tie it to the state of - // attachment of m_columns, because subtables with shared spec start out in - // a degenerate form where they do not have a 'columns' array. For these - // reasons, it is neccessary to define the notion of attachment for a table - // as follows: A table is attached if, and ony if m_column stores a non-null - // parent pointer. This works because even for degenerate subtables, - // m_columns is initialized with the correct parent pointer. - return m_columns.has_parent(); -} - -inline StringData Table::get_name() const noexcept -{ - REALM_ASSERT(is_attached()); - const Array& real_top = m_top.is_attached() ? m_top : m_columns; - ArrayParent* parent = real_top.get_parent(); - if (!parent) - return StringData(""); - size_t index_in_parent = real_top.get_ndx_in_parent(); - REALM_ASSERT(dynamic_cast(parent)); - return static_cast(parent)->get_child_name(index_in_parent); -} - -inline size_t Table::get_column_count() const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec.get_public_column_count(); -} - -inline StringData Table::get_column_name(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, get_column_count()); - return m_spec.get_column_name(ndx); -} - -inline size_t Table::get_column_index(StringData name) const noexcept -{ - REALM_ASSERT(is_attached()); - return m_spec.get_column_index(name); -} - -inline ColumnType Table::get_real_column_type(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_spec.get_column_count()); - return m_spec.get_column_type(ndx); -} - -inline DataType Table::get_column_type(size_t ndx) const noexcept -{ - REALM_ASSERT_3(ndx, <, m_spec.get_column_count()); - return m_spec.get_public_column_type(ndx); -} - -template -inline Col& Table::get_column(size_t ndx) -{ - ColumnBase& col = get_column_base(ndx); -#ifdef REALM_DEBUG - validate_column_type(col, col_type, ndx); -#endif - REALM_ASSERT(typeid(Col) == typeid(col)); - return static_cast(col); -} - -template -inline const Col& Table::get_column(size_t ndx) const noexcept -{ - const ColumnBase& col = get_column_base(ndx); -#ifdef REALM_DEBUG - validate_column_type(col, col_type, ndx); -#endif - REALM_ASSERT(typeid(Col) == typeid(col)); - return static_cast(col); -} - -inline bool Table::has_shared_type() const noexcept -{ - REALM_ASSERT(is_attached()); - return !m_top.is_attached(); -} - - -class Table::UnbindGuard { -public: - UnbindGuard(Table* table) noexcept - : m_table(table) - { - } - - ~UnbindGuard() noexcept - { - if (m_table) - m_table->unbind_ptr(); - } - - Table& operator*() const noexcept - { - return *m_table; - } - - Table* operator->() const noexcept - { - return m_table; - } - - Table* get() const noexcept - { - return m_table; - } - - Table* release() noexcept - { - Table* table = m_table; - m_table = nullptr; - return table; - } - -private: - Table* m_table; -}; - - -inline Table::Table(Allocator& alloc) - : m_top(alloc) - , m_columns(alloc) - , m_spec(alloc) -{ - m_ref_count = 1; // Explicitely managed lifetime - - ref_type ref = create_empty_table(alloc); // Throws - Parent* parent = nullptr; - size_t ndx_in_parent = 0; - init(ref, parent, ndx_in_parent); -} - -inline Table::Table(const Table& t, Allocator& alloc) - : m_top(alloc) - , m_columns(alloc) - , m_spec(alloc) -{ - m_ref_count = 1; // Explicitely managed lifetime - - ref_type ref = t.clone(alloc); // Throws - Parent* parent = nullptr; - size_t ndx_in_parent = 0; - init(ref, parent, ndx_in_parent); -} - -inline Table::Table(ref_count_tag, Allocator& alloc) - : m_top(alloc) - , m_columns(alloc) - , m_spec(alloc) -{ - m_ref_count = 0; // Lifetime managed by reference counting -} - -inline Allocator& Table::get_alloc() const -{ - return m_top.get_alloc(); -} - -inline TableRef Table::create(Allocator& alloc) -{ - std::unique_ptr
table(new Table(ref_count_tag(), alloc)); // Throws - ref_type ref = create_empty_table(alloc); // Throws - Parent* parent = nullptr; - size_t ndx_in_parent = 0; - table->init(ref, parent, ndx_in_parent); // Throws - return table.release()->get_table_ref(); -} - -inline TableRef Table::copy(Allocator& alloc) const -{ - std::unique_ptr
table(new Table(ref_count_tag(), alloc)); // Throws - ref_type ref = clone(alloc); // Throws - Parent* parent = nullptr; - size_t ndx_in_parent = 0; - table->init(ref, parent, ndx_in_parent); // Throws - return table.release()->get_table_ref(); -} - -// For use by queries -template -inline Columns Table::column(size_t column_ndx) -{ - std::vector link_chain = std::move(m_link_chain); - m_link_chain.clear(); - - // Check if user-given template type equals Realm type. Todo, we should clean up and reuse all our - // type traits (all the is_same() cases below). - const Table* table = get_link_chain_target(link_chain); - - realm::DataType ct = table->get_column_type(column_ndx); - if (std::is_same::value && ct != type_Int) - throw(LogicError::type_mismatch); - else if (std::is_same::value && ct != type_Bool) - throw(LogicError::type_mismatch); - else if (std::is_same::value && ct != type_OldDateTime) - throw(LogicError::type_mismatch); - else if (std::is_same::value && ct != type_Float) - throw(LogicError::type_mismatch); - else if (std::is_same::value && ct != type_Double) - throw(LogicError::type_mismatch); - - if (std::is_same::value || std::is_same::value || std::is_same::value) { - link_chain.push_back(column_ndx); - } - - return Columns(column_ndx, this, std::move(link_chain)); -} - -template -inline Columns Table::column(const Table& origin, size_t origin_col_ndx) -{ - static_assert(std::is_same::value, ""); - - size_t origin_table_ndx = origin.get_index_in_group(); - const Table& current_target_table = *get_link_chain_target(m_link_chain); - size_t backlink_col_ndx = current_target_table.m_spec.find_backlink_column(origin_table_ndx, origin_col_ndx); - - std::vector link_chain = std::move(m_link_chain); - m_link_chain.clear(); - link_chain.push_back(backlink_col_ndx); - - return Columns(backlink_col_ndx, this, std::move(link_chain)); -} - -template -SubQuery Table::column(size_t column_ndx, Query subquery) -{ - static_assert(std::is_same::value, "A subquery must involve a link list or backlink column"); - return SubQuery(column(column_ndx), std::move(subquery)); -} - -template -SubQuery Table::column(const Table& origin, size_t origin_col_ndx, Query subquery) -{ - static_assert(std::is_same::value, "A subquery must involve a link list or backlink column"); - return SubQuery(column(origin, origin_col_ndx), std::move(subquery)); -} - -// For use by queries -inline Table& Table::link(size_t link_column) -{ - m_link_chain.push_back(link_column); - return *this; -} - -inline Table& Table::backlink(const Table& origin, size_t origin_col_ndx) -{ - size_t origin_table_ndx = origin.get_index_in_group(); - const Table& current_target_table = *get_link_chain_target(m_link_chain); - size_t backlink_col_ndx = current_target_table.m_spec.find_backlink_column(origin_table_ndx, origin_col_ndx); - return link(backlink_col_ndx); -} - -inline bool Table::is_empty() const noexcept -{ - return m_size == 0; -} - -inline size_t Table::size() const noexcept -{ - return m_size; -} - -inline Table::RowExpr Table::get(size_t row_ndx) noexcept -{ - REALM_ASSERT_3(row_ndx, <, size()); - return RowExpr(this, row_ndx); -} - -inline Table::ConstRowExpr Table::get(size_t row_ndx) const noexcept -{ - REALM_ASSERT_3(row_ndx, <, size()); - return ConstRowExpr(this, row_ndx); -} - -inline Table::RowExpr Table::front() noexcept -{ - return get(0); -} - -inline Table::ConstRowExpr Table::front() const noexcept -{ - return get(0); -} - -inline Table::RowExpr Table::back() noexcept -{ - return get(m_size - 1); -} - -inline Table::ConstRowExpr Table::back() const noexcept -{ - return get(m_size - 1); -} - -inline Table::RowExpr Table::operator[](size_t row_ndx) noexcept -{ - return get(row_ndx); -} - -inline Table::ConstRowExpr Table::operator[](size_t row_ndx) const noexcept -{ - return get(row_ndx); -} - -inline size_t Table::add_empty_row(size_t num_rows) -{ - size_t row_ndx = m_size; - insert_empty_row(row_ndx, num_rows); // Throws - return row_ndx; // Return index of first new row -} - -inline const Table* Table::get_subtable_ptr(size_t col_ndx, size_t row_ndx) const -{ - return const_cast(this)->get_subtable_ptr(col_ndx, row_ndx); // Throws -} - -inline bool Table::is_null_link(size_t col_ndx, size_t row_ndx) const noexcept -{ - return get_link(col_ndx, row_ndx) == realm::npos; -} - -inline ConstTableRef Table::get_link_target(size_t col_ndx) const noexcept -{ - return const_cast(this)->get_link_target(col_ndx); -} - -template -inline void Table::set_enum(size_t column_ndx, size_t row_ndx, E value) -{ - set_int(column_ndx, row_ndx, value); -} - -inline void Table::nullify_link(size_t col_ndx, size_t row_ndx) -{ - set_link(col_ndx, row_ndx, realm::npos); -} - -inline TableRef Table::get_subtable(size_t column_ndx, size_t row_ndx) -{ - return TableRef(get_subtable_ptr(column_ndx, row_ndx)); -} - -inline ConstTableRef Table::get_subtable(size_t column_ndx, size_t row_ndx) const -{ - return ConstTableRef(get_subtable_ptr(column_ndx, row_ndx)); -} - -inline ConstTableRef Table::get_parent_table(size_t* column_ndx_out) const noexcept -{ - return ConstTableRef(get_parent_table_ptr(column_ndx_out)); -} - -inline TableRef Table::get_parent_table(size_t* column_ndx_out) noexcept -{ - return TableRef(get_parent_table_ptr(column_ndx_out)); -} - -inline bool Table::is_group_level() const noexcept -{ - return bool(get_parent_group()); -} - -inline bool Table::operator==(const Table& t) const -{ - return m_spec == t.m_spec && compare_rows(t); // Throws -} - -inline bool Table::operator!=(const Table& t) const -{ - return !(*this == t); // Throws -} - -inline bool Table::is_degenerate() const noexcept -{ - return !m_columns.is_attached(); -} - -inline void Table::set_into_mixed(Table* parent, size_t col_ndx, size_t row_ndx) const -{ - parent->set_mixed_subtable(col_ndx, row_ndx, this); -} - -inline size_t Table::get_size_from_ref(ref_type top_ref, Allocator& alloc) noexcept -{ - const char* top_header = alloc.translate(top_ref); - std::pair p = Array::get_two(top_header, 0); - ref_type spec_ref = to_ref(p.first), columns_ref = to_ref(p.second); - return get_size_from_ref(spec_ref, columns_ref, alloc); -} - -inline Table* Table::get_parent_table_ptr(size_t* column_ndx_out) noexcept -{ - const Table* parent = const_cast(this)->get_parent_table_ptr(column_ndx_out); - return const_cast(parent); -} - -inline bool Table::is_link_type(ColumnType col_type) noexcept -{ - return col_type == col_type_Link || col_type == col_type_LinkList; -} - -inline size_t* Table::record_subtable_path(size_t* begin, size_t* end) const noexcept -{ - const Array& real_top = m_top.is_attached() ? m_top : m_columns; - size_t index_in_parent = real_top.get_ndx_in_parent(); - REALM_ASSERT_3(begin, <, end); - *begin++ = index_in_parent; - ArrayParent* parent = real_top.get_parent(); - REALM_ASSERT(parent); - REALM_ASSERT(dynamic_cast(parent)); - return static_cast(parent)->record_subtable_path(begin, end); -} - -inline size_t* Table::Parent::record_subtable_path(size_t* begin, size_t*) noexcept -{ - return begin; -} - -template -typename T::RowAccessor Table::get_link_accessor(size_t column_ndx, size_t row_ndx) -{ - size_t row_pos_in_target = get_link(column_ndx, row_ndx); - TableRef target_table = get_link_target(column_ndx); - - Table* table = &*target_table; - T* typed_table = reinterpret_cast(table); - return (*typed_table)[row_pos_in_target]; -} - -inline bool Table::is_marked() const noexcept -{ - return m_mark; -} - -inline void Table::mark() noexcept -{ - m_mark = true; -} - -inline void Table::unmark() noexcept -{ - m_mark = false; -} - -inline Replication* Table::get_repl() noexcept -{ - return m_top.get_alloc().get_replication(); -} - -inline void Table::set_ndx_in_parent(size_t ndx_in_parent) noexcept -{ - if (m_top.is_attached()) { - // Root table (independent descriptor) - m_top.set_ndx_in_parent(ndx_in_parent); - } - else { - // Subtable with shared descriptor - m_columns.set_ndx_in_parent(ndx_in_parent); - } -} - -// This class groups together information about the target of a link column -// This is not a valid link if the target table == nullptr -struct LinkTargetInfo { - LinkTargetInfo(Table* target = nullptr, size_t backlink_ndx = realm::npos) - : m_target_table(target) - , m_backlink_col_ndx(backlink_ndx) - { - } - bool is_valid() const - { - return (m_target_table != nullptr); - } - Table* m_target_table; - size_t m_backlink_col_ndx; // a value of npos indicates the backlink should be appended -}; - -// The purpose of this class is to give internal access to some, but -// not all of the non-public parts of the Table class. -class _impl::TableFriend { -public: - typedef Table::UnbindGuard UnbindGuard; - - static ref_type create_empty_table(Allocator& alloc) - { - return Table::create_empty_table(alloc); // Throws - } - - static ref_type clone(const Table& table, Allocator& alloc) - { - return table.clone(alloc); // Throws - } - - static ref_type clone_columns(const Table& table, Allocator& alloc) - { - return table.clone_columns(alloc); // Throws - } - - static Table* create_accessor(Allocator& alloc, ref_type top_ref, Table::Parent* parent, size_t ndx_in_parent) - { - std::unique_ptr
table(new Table(Table::ref_count_tag(), alloc)); // Throws - table->init(top_ref, parent, ndx_in_parent); // Throws - return table.release(); - } - - static Table* create_accessor(ConstSubspecRef shared_spec, Table::Parent* parent_column, size_t parent_row_ndx) - { - Allocator& alloc = shared_spec.get_alloc(); - std::unique_ptr
table(new Table(Table::ref_count_tag(), alloc)); // Throws - table->init(shared_spec, parent_column, parent_row_ndx); // Throws - return table.release(); - } - - // Intended to be used only by Group::create_table_accessor() - static Table* create_incomplete_accessor(Allocator& alloc, ref_type top_ref, Table::Parent* parent, - size_t ndx_in_parent) - { - std::unique_ptr
table(new Table(Table::ref_count_tag(), alloc)); // Throws - bool skip_create_column_accessors = true; - table->init(top_ref, parent, ndx_in_parent, skip_create_column_accessors); // Throws - return table.release(); - } - - // Intended to be used only by Group::create_table_accessor() - static void complete_accessor(Table& table) - { - table.refresh_column_accessors(); // Throws - } - - static void set_top_parent(Table& table, ArrayParent* parent, size_t ndx_in_parent) noexcept - { - table.m_top.set_parent(parent, ndx_in_parent); - } - - static void update_from_parent(Table& table, size_t old_baseline) noexcept - { - table.update_from_parent(old_baseline); - } - - static void detach(Table& table) noexcept - { - table.detach(); - } - - static void discard_row_accessors(Table& table) noexcept - { - table.discard_row_accessors(); - } - - static void discard_child_accessors(Table& table) noexcept - { - table.discard_child_accessors(); - } - - static void discard_subtable_accessor(Table& table, size_t col_ndx, size_t row_ndx) noexcept - { - table.discard_subtable_accessor(col_ndx, row_ndx); - } - - static void bind_ptr(Table& table) noexcept - { - table.bind_ptr(); - } - - static void unbind_ptr(Table& table) noexcept - { - table.unbind_ptr(); - } - - static bool compare_rows(const Table& a, const Table& b) - { - return a.compare_rows(b); // Throws - } - - static size_t get_size_from_ref(ref_type ref, Allocator& alloc) noexcept - { - return Table::get_size_from_ref(ref, alloc); - } - - static size_t get_size_from_ref(ref_type spec_ref, ref_type columns_ref, Allocator& alloc) noexcept - { - return Table::get_size_from_ref(spec_ref, columns_ref, alloc); - } - - static Spec& get_spec(Table& table) noexcept - { - return table.m_spec; - } - - static const Spec& get_spec(const Table& table) noexcept - { - return table.m_spec; - } - - static ColumnBase& get_column(const Table& table, size_t col_ndx) - { - return *table.m_cols[col_ndx]; - } - - static void do_remove(Table& table, size_t row_ndx) - { - bool broken_reciprocal_backlinks = false; - table.do_remove(row_ndx, broken_reciprocal_backlinks); // Throws - } - - static void do_move_last_over(Table& table, size_t row_ndx) - { - bool broken_reciprocal_backlinks = false; - table.do_move_last_over(row_ndx, broken_reciprocal_backlinks); // Throws - } - - static void do_swap_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) - { - table.do_swap_rows(row_ndx_1, row_ndx_2); // Throws - } - - static void do_merge_rows(Table& table, size_t row_ndx, size_t new_row_ndx) - { - table.do_merge_rows(row_ndx, new_row_ndx); // Throws - } - - static void do_clear(Table& table) - { - bool broken_reciprocal_backlinks = false; - table.do_clear(broken_reciprocal_backlinks); // Throws - } - - static void do_set_link(Table& table, size_t col_ndx, size_t row_ndx, size_t target_row_ndx) - { - table.do_set_link(col_ndx, row_ndx, target_row_ndx); // Throws - } - - static size_t get_num_strong_backlinks(const Table& table, size_t row_ndx) noexcept - { - return table.get_num_strong_backlinks(row_ndx); - } - - static void cascade_break_backlinks_to(Table& table, size_t row_ndx, CascadeState& state) - { - table.cascade_break_backlinks_to(row_ndx, state); // Throws - } - - static void remove_backlink_broken_rows(Table& table, const CascadeState& rows) - { - table.remove_backlink_broken_rows(rows); // Throws - } - - static size_t* record_subtable_path(const Table& table, size_t* begin, size_t* end) noexcept - { - return table.record_subtable_path(begin, end); - } - - static void insert_column(Descriptor& desc, size_t column_ndx, DataType type, StringData name, - LinkTargetInfo& link, bool nullable = false) - { - Table::do_insert_column(desc, column_ndx, type, name, link, nullable); // Throws - } - - static void insert_column_unless_exists(Descriptor& desc, size_t column_ndx, DataType type, StringData name, - LinkTargetInfo link, bool nullable = false, bool* was_inserted = nullptr) - { - Table::do_insert_column_unless_exists(desc, column_ndx, type, name, link, nullable, was_inserted); // Throws - } - - static void erase_column(Descriptor& desc, size_t column_ndx) - { - Table::do_erase_column(desc, column_ndx); // Throws - } - - static void rename_column(Descriptor& desc, size_t column_ndx, StringData name) - { - Table::do_rename_column(desc, column_ndx, name); // Throws - } - - static void move_column(Descriptor& desc, size_t col_ndx_1, size_t col_ndx_2) - { - Table::do_move_column(desc, col_ndx_1, col_ndx_2); // Throws - } - - static void set_link_type(Table& table, size_t column_ndx, LinkType link_type) - { - table.do_set_link_type(column_ndx, link_type); // Throws - } - - static void erase_row(Table& table, size_t row_ndx, bool is_move_last_over) - { - table.erase_row(row_ndx, is_move_last_over); // Throws - } - - static void batch_erase_rows(Table& table, const IntegerColumn& row_indexes, bool is_move_last_over) - { - table.batch_erase_rows(row_indexes, is_move_last_over); // Throws - } - - static Table* get_subtable_accessor(Table& table, size_t col_ndx, size_t row_ndx) noexcept - { - return table.get_subtable_accessor(col_ndx, row_ndx); - } - - static const Table* get_link_target_table_accessor(const Table& table, size_t col_ndx) noexcept - { - return const_cast(table).get_link_target_table_accessor(col_ndx); - } - - static Table* get_link_target_table_accessor(Table& table, size_t col_ndx) noexcept - { - return table.get_link_target_table_accessor(col_ndx); - } - - static void adj_acc_insert_rows(Table& table, size_t row_ndx, size_t num_rows) noexcept - { - table.adj_acc_insert_rows(row_ndx, num_rows); - } - - static void adj_acc_erase_row(Table& table, size_t row_ndx) noexcept - { - table.adj_acc_erase_row(row_ndx); - } - - static void adj_acc_swap_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept - { - table.adj_acc_swap_rows(row_ndx_1, row_ndx_2); - } - - static void adj_acc_merge_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept - { - table.adj_acc_merge_rows(row_ndx_1, row_ndx_2); - } - - static void adj_acc_move_over(Table& table, size_t from_row_ndx, size_t to_row_ndx) noexcept - { - table.adj_acc_move_over(from_row_ndx, to_row_ndx); - } - - static void adj_acc_clear_root_table(Table& table) noexcept - { - table.adj_acc_clear_root_table(); - } - - static void adj_acc_clear_nonroot_table(Table& table) noexcept - { - table.adj_acc_clear_nonroot_table(); - } - - static void adj_insert_column(Table& table, size_t col_ndx) - { - table.adj_insert_column(col_ndx); // Throws - } - - static void adj_add_column(Table& table) - { - size_t num_cols = table.m_cols.size(); - table.adj_insert_column(num_cols); // Throws - } - - static void adj_erase_column(Table& table, size_t col_ndx) noexcept - { - table.adj_erase_column(col_ndx); - } - - static void adj_move_column(Table& table, size_t col_ndx_1, size_t col_ndx_2) noexcept - { - table.adj_move_column(col_ndx_1, col_ndx_2); - } - - static bool is_marked(const Table& table) noexcept - { - return table.is_marked(); - } - - static void mark(Table& table) noexcept - { - table.mark(); - } - - static void unmark(Table& table) noexcept - { - table.unmark(); - } - - static void recursive_mark(Table& table) noexcept - { - table.recursive_mark(); - } - - static void mark_link_target_tables(Table& table, size_t col_ndx_begin) noexcept - { - table.mark_link_target_tables(col_ndx_begin); - } - - static void mark_opposite_link_tables(Table& table) noexcept - { - table.mark_opposite_link_tables(); - } - - static DescriptorRef get_root_table_desc_accessor(Table& root_table) noexcept - { - return root_table.m_descriptor.lock(); - } - - typedef Table::AccessorUpdater AccessorUpdater; - static void update_accessors(Table& table, const size_t* col_path_begin, const size_t* col_path_end, - AccessorUpdater& updater) - { - table.update_accessors(col_path_begin, col_path_end, updater); // Throws - } - - static void refresh_accessor_tree(Table& table) - { - table.refresh_accessor_tree(); // Throws - } - - static void set_ndx_in_parent(Table& table, size_t ndx_in_parent) noexcept - { - table.set_ndx_in_parent(ndx_in_parent); - } - - static void set_shared_subspec_ndx_in_parent(Table& table, size_t spec_ndx_in_parent) noexcept - { - table.m_spec.set_ndx_in_parent(spec_ndx_in_parent); - } - - static bool is_link_type(ColumnType type) noexcept - { - return Table::is_link_type(type); - } - - static void bump_version(Table& table, bool bump_global = true) noexcept - { - table.bump_version(bump_global); - } - - static bool is_cross_table_link_target(const Table& table) - { - return table.is_cross_table_link_target(); - } - - static Group* get_parent_group(const Table& table) noexcept - { - return table.get_parent_group(); - } - - static Replication* get_repl(Table& table) noexcept - { - return table.get_repl(); - } - - static void register_view(Table& table, const TableViewBase* view) - { - table.register_view(view); // Throws - } - - static void unregister_view(Table& table, const TableViewBase* view) noexcept - { - table.unregister_view(view); - } -}; - - -} // namespace realm - -#endif // REALM_TABLE_HPP diff --git a/Example/Pods/Realm/include/core/realm/table_accessors.hpp b/Example/Pods/Realm/include/core/realm/table_accessors.hpp deleted file mode 100644 index c0a9a5f..0000000 --- a/Example/Pods/Realm/include/core/realm/table_accessors.hpp +++ /dev/null @@ -1,1981 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 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. - * - **************************************************************************/ - -#ifndef REALM_TABLE_ACCESSORS_HPP -#define REALM_TABLE_ACCESSORS_HPP - -#include -#include - -#include -#include - -#include - -namespace realm { - - -/// A convenience base class for Spec classes that are to be used with -/// BasicTable. -/// -/// There are two reasons why you might want to derive your spec class -/// from this one. First, it offers short hand names for each of the -/// available column types. Second, it makes it easier when you do not -/// want to specify colum names or convenience methods, since suitable -/// fallbacks are defined here. -struct SpecBase { - typedef int64_t Int; - typedef bool Bool; - typedef realm::OldDateTime OldDateTime; - typedef float Float; - typedef double Double; - typedef realm::StringData String; - typedef realm::BinaryData Binary; - typedef realm::Mixed Mixed; - - template - class Enum { - public: - typedef E enum_type; - Enum(E v) - : m_value(v) - { - } - operator E() const - { - return m_value; - } - - private: - E m_value; - }; - - template - class Subtable { - public: - typedef T table_type; - Subtable(T* t) - : m_table(t) - { - } - operator T*() const - { - return m_table; - } - - private: - T* m_table; - }; - - /// By default, there are no static column names defined for a - /// BasicTable. One may define a set of column mames as follows: - /// - /// \code{.cpp} - /// - /// struct MyTableSpec: SpecBase { - /// typedef TypeAppend::type Columns1; - /// typedef TypeAppend::type Columns; - /// - /// template