From a7beed3618ee39b0f8c37fa0ce4835e0b8462531 Mon Sep 17 00:00:00 2001 From: Mccc Date: Thu, 13 Jun 2024 15:06:23 +0800 Subject: [PATCH] decoder & encoder --- Document/README/CompareWithHandyJSON.md | 47 + Document/README/LearnMore.md | 38 + Document/README/Usages.md | 525 + ...47\350\241\214\351\200\273\350\276\221.md" | 110 + Document/TestCaseSpecification.xmind | Bin 0 -> 159664 bytes Example/Podfile | 4 +- Example/Podfile.lock | 19 +- .../Local Podspecs/SmartCodable.podspec.json | 9 +- Example/Pods/Manifest.lock | 19 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 3495 +-- Example/Pods/SQLiteRepairKit/LICENSE | 415 - Example/Pods/SQLiteRepairKit/README.md | 287 - .../SQLiteRepairKit/repair/SQLiteRepairKit.h | 192 - .../Pods/SQLiteRepairKit/repair/sqliterk.c | 370 - .../Pods/SQLiteRepairKit/repair/sqliterk.h | 44 - .../SQLiteRepairKit/repair/sqliterk_api.c | 184 - .../SQLiteRepairKit/repair/sqliterk_btree.c | 667 - .../SQLiteRepairKit/repair/sqliterk_btree.h | 86 - .../SQLiteRepairKit/repair/sqliterk_column.c | 115 - .../SQLiteRepairKit/repair/sqliterk_column.h | 37 - .../SQLiteRepairKit/repair/sqliterk_crypto.c | 244 - .../SQLiteRepairKit/repair/sqliterk_crypto.h | 43 - .../Pods/SQLiteRepairKit/repair/sqliterk_os.c | 193 - .../Pods/SQLiteRepairKit/repair/sqliterk_os.h | 65 - .../repair/sqliterk_output.cpp | 1170 - .../SQLiteRepairKit/repair/sqliterk_pager.c | 606 - .../SQLiteRepairKit/repair/sqliterk_pager.h | 112 - .../SQLiteRepairKit/repair/sqliterk_util.c | 180 - .../SQLiteRepairKit/repair/sqliterk_util.h | 46 - .../SQLiteRepairKit/repair/sqliterk_values.c | 402 - .../SQLiteRepairKit/repair/sqliterk_values.h | 58 - Example/Pods/SnapKit/README.md | 4 +- Example/Pods/SnapKit/Sources/Constraint.swift | 6 +- .../Sources/ConstraintAttributes.swift | 4 +- .../SnapKit/Sources/ConstraintConfig.swift | 2 +- .../Sources/ConstraintConstantTarget.swift | 10 +- .../Pods/SnapKit/Sources/ConstraintDSL.swift | 2 +- .../Sources/ConstraintDescription.swift | 2 +- .../ConstraintDirectionalInsetTarget.swift | 4 +- .../Sources/ConstraintDirectionalInsets.swift | 4 +- .../Sources/ConstraintInsetTarget.swift | 2 +- .../SnapKit/Sources/ConstraintInsets.swift | 4 +- .../Pods/SnapKit/Sources/ConstraintItem.swift | 2 +- .../ConstraintLayoutGuide+Extensions.swift | 2 +- .../Sources/ConstraintLayoutGuide.swift | 4 +- .../Sources/ConstraintLayoutGuideDSL.swift | 2 +- .../Sources/ConstraintLayoutSupport.swift | 4 +- .../Sources/ConstraintLayoutSupportDSL.swift | 2 +- .../SnapKit/Sources/ConstraintMaker.swift | 2 +- .../Sources/ConstraintMakerEditable.swift | 4 +- .../Sources/ConstraintMakerExtendable.swift | 2 +- .../Sources/ConstraintMakerFinalizable.swift | 2 +- .../ConstraintMakerPrioritizable.swift | 2 +- .../ConstraintMakerRelatable+Extensions.swift | 4 +- .../Sources/ConstraintMakerRelatable.swift | 2 +- .../Sources/ConstraintMultiplierTarget.swift | 2 +- .../Sources/ConstraintOffsetTarget.swift | 2 +- .../SnapKit/Sources/ConstraintPriority.swift | 2 +- .../Sources/ConstraintPriorityTarget.swift | 4 +- .../Sources/ConstraintRelatableTarget.swift | 4 +- .../SnapKit/Sources/ConstraintRelation.swift | 2 +- .../Sources/ConstraintView+Extensions.swift | 2 +- .../Pods/SnapKit/Sources/ConstraintView.swift | 4 +- .../SnapKit/Sources/ConstraintViewDSL.swift | 2 +- Example/Pods/SnapKit/Sources/Debugging.swift | 4 +- .../SnapKit/Sources/LayoutConstraint.swift | 2 +- .../Sources/LayoutConstraintItem.swift | 2 +- .../Pods/SnapKit/Sources/Typealiases.swift | 2 +- .../Sources/UILayoutSupport+Extensions.swift | 2 +- ...tCodable_Example-acknowledgements.markdown | 866 - ...martCodable_Example-acknowledgements.plist | 884 - .../Pods-SmartCodable_Example-frameworks.sh | 6 - .../Pods-SmartCodable_Example.debug.xcconfig | 6 +- ...Pods-SmartCodable_Example.release.xcconfig | 6 +- .../Pods-SmartCodable_Tests.debug.xcconfig | 6 +- .../Pods-SmartCodable_Tests.release.xcconfig | 6 +- .../SQLiteRepairKit/SQLiteRepairKit-dummy.m | 5 - .../SQLiteRepairKit-prefix.pch | 12 - .../SQLiteRepairKit-umbrella.h | 17 - .../SQLiteRepairKit.debug.xcconfig | 18 - .../SQLiteRepairKit/SQLiteRepairKit.modulemap | 6 - .../SQLiteRepairKit.release.xcconfig | 18 - .../SmartCodable/SmartCodable-Info.plist | 2 +- ...Bundle-SnapKit_Privacy-SnapKit-Info.plist} | 8 +- .../WCDB.swift/WCDB.swift-Info.plist | 26 - .../WCDB.swift/WCDB.swift-dummy.m | 5 - .../WCDB.swift/WCDB.swift-prefix.pch | 12 - .../WCDB.swift/WCDB.swift-umbrella.h | 18 - .../WCDB.swift/WCDB.swift.debug.xcconfig | 25 - .../WCDB.swift/WCDB.swift.modulemap | 6 - .../WCDB.swift/WCDB.swift.release.xcconfig | 25 - .../WCDBOptimizedSQLCipher-Info.plist | 26 - .../WCDBOptimizedSQLCipher-dummy.m | 5 - .../WCDBOptimizedSQLCipher-prefix.pch | 12 - .../WCDBOptimizedSQLCipher-umbrella.h | 18 - .../WCDBOptimizedSQLCipher.debug.xcconfig | 21 - .../WCDBOptimizedSQLCipher.modulemap | 6 - .../WCDBOptimizedSQLCipher.release.xcconfig | 21 - Example/Pods/WCDB.swift/LICENSE | 415 - Example/Pods/WCDB.swift/README.md | 287 - .../swift/source/abstract/Column.swift | 42 - .../swift/source/abstract/ColumnDef.swift | 114 - .../swift/source/abstract/ColumnIndex.swift | 45 - .../swift/source/abstract/ColumnResult.swift | 41 - .../swift/source/abstract/ColumnType.swift | 47 - .../swift/source/abstract/Conflict.swift | 44 - .../swift/source/abstract/Convertible.swift | 107 - .../swift/source/abstract/Describable.swift | 24 - .../swift/source/abstract/Expression.swift | 115 - .../swift/source/abstract/ForeignKey.swift | 103 - .../source/abstract/FundamentalValue.swift | 155 - .../swift/source/abstract/Handle.swift | 285 - .../source/abstract/HandleStatement.swift | 216 - .../swift/source/abstract/JoinClause.swift | 96 - .../swift/source/abstract/LiteralValue.swift | 110 - .../source/abstract/ModuleArgument.swift | 45 - .../swift/source/abstract/Operable.swift | 572 - .../swift/source/abstract/Order.swift | 35 - .../swift/source/abstract/OrderTerm.swift | 35 - .../swift/source/abstract/Pragma.swift | 109 - .../swift/source/abstract/Statement.swift | 48 - .../source/abstract/StatementAlterTable.swift | 48 - .../source/abstract/StatementAttach.swift | 35 - .../abstract/StatementCreateIndex.swift | 66 - .../abstract/StatementCreateTable.swift | 66 - .../StatementCreateVirtualTable.swift | 53 - .../source/abstract/StatementDelete.swift | 94 - .../source/abstract/StatementDetach.swift | 35 - .../source/abstract/StatementDropIndex.swift | 39 - .../source/abstract/StatementDropTable.swift | 38 - .../source/abstract/StatementExplain.swift | 41 - .../source/abstract/StatementInsert.swift | 64 - .../source/abstract/StatementPragma.swift | 41 - .../source/abstract/StatementReindex.swift | 35 - .../source/abstract/StatementRelease.swift | 35 - .../source/abstract/StatementRollback.swift | 37 - .../source/abstract/StatementSavepoint.swift | 35 - .../source/abstract/StatementSelect.swift | 147 - .../abstract/StatementTransaction.swift | 89 - .../source/abstract/StatementUpdate.swift | 114 - .../source/abstract/StatementVacuum.swift | 35 - .../swift/source/abstract/Subquery.swift | 54 - .../source/abstract/TableConstraint.swift | 75 - .../swift/source/abstract/Tokenize.swift | 171 - .../swift/source/abstract/Tracer.swift | 135 - .../swift/source/builtin/CodableType.swift | 324 - .../source/builtin/CommonStatement.swift | 45 - .../swift/source/builtin/Master.swift | 45 - .../swift/source/core/base/Config.swift | 117 - .../swift/source/core/base/Core.swift | 160 - .../source/core/base/CoreStatement.swift | 263 - .../swift/source/core/base/Database.swift | 733 - .../swift/source/core/base/HandlePool.swift | 221 - .../source/core/base/RecyclableCore.swift | 35 - .../swift/source/core/base/Transaction.swift | 176 - .../binding/ColumnConstraintBinding.swift | 97 - .../source/core/binding/IndexBinding.swift | 47 - .../swift/source/core/binding/Property.swift | 65 - .../source/core/binding/Redirectable.swift | 37 - .../source/core/binding/TableBinding.swift | 155 - .../core/binding/TableConstraintBinding.swift | 104 - .../core/binding/VirtualTableBinding.swift | 43 - .../source/core/codable/CodingTableKey.swift | 100 - .../source/core/codable/ColumnCodable.swift | 41 - .../core/codable/ColumnTypeDecoder.swift | 203 - .../source/core/codable/TableCodable.swift | 53 - .../source/core/codable/TableDecoder.swift | 326 - .../source/core/codable/TableEncoder.swift | 421 - .../swift/source/core/fts/WCDBTokenize.swift | 344 - .../source/core/interface/ChainCall.swift | 348 - .../swift/source/core/interface/Declare.swift | 28 - .../swift/source/core/interface/Delete.swift | 129 - .../swift/source/core/interface/Insert.swift | 117 - .../source/core/interface/Interface.swift | 931 - .../source/core/interface/MultiSelect.swift | 132 - .../source/core/interface/RowSelect.swift | 123 - .../swift/source/core/interface/Select.swift | 88 - .../source/core/interface/Selectable.swift | 143 - .../swift/source/core/interface/Table.swift | 564 - .../core/interface/TableInterface.swift | 132 - .../swift/source/core/interface/Update.swift | 165 - .../WCDB.swift/swift/source/util/Atomic.swift | 94 - .../swift/source/util/ConcurrentList.swift | 55 - .../swift/source/util/Convenience.swift | 256 - .../WCDB.swift/swift/source/util/Error.swift | 412 - .../WCDB.swift/swift/source/util/File.swift | 111 - .../WCDB.swift/swift/source/util/Lock.swift | 155 - .../swift/source/util/Optional.swift | 35 - .../WCDB.swift/swift/source/util/RWLock.swift | 81 - .../swift/source/util/Recyclable.swift | 45 - .../swift/source/util/SQLite-Bridging.c | 47 - .../swift/source/util/SQLite-Bridging.h | 53 - .../swift/source/util/SQLite-Bridging.swift | 25 - .../swift/source/util/SteadyClock.swift | 49 - .../WCDB.swift/swift/source/util/Tagged.swift | 43 - .../swift/source/util/ThreadLocal.swift | 60 - .../swift/source/util/TimedQueue.swift | 88 - .../swift/source/util/WCDB-Bridging.h | 22 - Example/Pods/WCDBOptimizedSQLCipher/LICENSE | 24 - Example/Pods/WCDBOptimizedSQLCipher/README.md | 434 - .../WCDBOptimizedSQLCipher/ext/fts3/fts3.c | 6005 ----- .../WCDBOptimizedSQLCipher/ext/fts3/fts3.h | 26 - .../WCDBOptimizedSQLCipher/ext/fts3/fts3Int.h | 633 - .../ext/fts3/fts3_aux.c | 551 - .../ext/fts3/fts3_expr.c | 1291 - .../ext/fts3/fts3_hash.c | 383 - .../ext/fts3/fts3_hash.h | 112 - .../ext/fts3/fts3_icu.c | 262 - .../ext/fts3/fts3_porter.c | 662 - .../ext/fts3/fts3_snippet.c | 1724 -- .../ext/fts3/fts3_tokenize_vtab.c | 455 - .../ext/fts3/fts3_tokenizer.c | 516 - .../ext/fts3/fts3_tokenizer.h | 161 - .../ext/fts3/fts3_tokenizer1.c | 234 - .../ext/fts3/fts3_unicode.c | 396 - .../ext/fts3/fts3_unicode2.c | 383 - .../ext/fts3/fts3_write.c | 5709 ---- .../Pods/WCDBOptimizedSQLCipher/ext/icu/icu.c | 553 - .../ext/icu/sqliteicu.h | 27 - .../ext/rbu/sqlite3rbu.c | 4945 ---- .../ext/rbu/sqlite3rbu.h | 605 - .../WCDBOptimizedSQLCipher/ext/rtree/rtree.c | 4468 ---- .../WCDBOptimizedSQLCipher/ext/rtree/rtree.h | 30 - .../ext/rtree/sqlite3rtree.h | 117 - .../ext/userauth/sqlite3userauth.h | 96 - .../ext/userauth/userauth.c | 355 - Example/Pods/WCDBOptimizedSQLCipher/fts5.c | 22114 ---------------- Example/Pods/WCDBOptimizedSQLCipher/fts5.h | 575 - .../Pods/WCDBOptimizedSQLCipher/keywordhash.h | 329 - Example/Pods/WCDBOptimizedSQLCipher/opcodes.c | 189 - Example/Pods/WCDBOptimizedSQLCipher/opcodes.h | 217 - Example/Pods/WCDBOptimizedSQLCipher/parse.c | 5318 ---- Example/Pods/WCDBOptimizedSQLCipher/parse.h | 180 - Example/Pods/WCDBOptimizedSQLCipher/sqlite3.h | 11746 -------- .../Pods/WCDBOptimizedSQLCipher/src/alter.c | 1642 -- .../Pods/WCDBOptimizedSQLCipher/src/analyze.c | 1936 -- .../Pods/WCDBOptimizedSQLCipher/src/attach.c | 629 - .../Pods/WCDBOptimizedSQLCipher/src/auth.c | 273 - .../Pods/WCDBOptimizedSQLCipher/src/backup.c | 823 - .../Pods/WCDBOptimizedSQLCipher/src/bitvec.c | 411 - .../Pods/WCDBOptimizedSQLCipher/src/btmutex.c | 308 - .../Pods/WCDBOptimizedSQLCipher/src/btree.c | 10371 -------- .../Pods/WCDBOptimizedSQLCipher/src/btree.h | 398 - .../WCDBOptimizedSQLCipher/src/btreeInt.h | 711 - .../Pods/WCDBOptimizedSQLCipher/src/build.c | 4674 ---- .../WCDBOptimizedSQLCipher/src/callback.c | 488 - .../WCDBOptimizedSQLCipher/src/complete.c | 290 - .../Pods/WCDBOptimizedSQLCipher/src/crypto.c | 1180 - .../Pods/WCDBOptimizedSQLCipher/src/crypto.h | 316 - .../WCDBOptimizedSQLCipher/src/crypto_cc.c | 200 - .../WCDBOptimizedSQLCipher/src/crypto_impl.c | 1539 -- .../src/crypto_libtomcrypt.c | 300 - .../Pods/WCDBOptimizedSQLCipher/src/ctime.c | 767 - .../Pods/WCDBOptimizedSQLCipher/src/date.c | 1249 - .../Pods/WCDBOptimizedSQLCipher/src/dbstat.c | 730 - .../Pods/WCDBOptimizedSQLCipher/src/delete.c | 964 - .../Pods/WCDBOptimizedSQLCipher/src/expr.c | 5444 ---- .../Pods/WCDBOptimizedSQLCipher/src/fault.c | 87 - .../Pods/WCDBOptimizedSQLCipher/src/fkey.c | 1431 - .../Pods/WCDBOptimizedSQLCipher/src/func.c | 2037 -- .../Pods/WCDBOptimizedSQLCipher/src/global.c | 315 - .../Pods/WCDBOptimizedSQLCipher/src/hash.c | 269 - .../Pods/WCDBOptimizedSQLCipher/src/hash.h | 96 - .../Pods/WCDBOptimizedSQLCipher/src/hwtime.h | 85 - .../Pods/WCDBOptimizedSQLCipher/src/insert.c | 2439 -- .../Pods/WCDBOptimizedSQLCipher/src/legacy.c | 141 - .../Pods/WCDBOptimizedSQLCipher/src/loadext.c | 854 - .../Pods/WCDBOptimizedSQLCipher/src/main.c | 4429 ---- .../Pods/WCDBOptimizedSQLCipher/src/malloc.c | 726 - .../Pods/WCDBOptimizedSQLCipher/src/mem0.c | 59 - .../Pods/WCDBOptimizedSQLCipher/src/mem1.c | 291 - .../Pods/WCDBOptimizedSQLCipher/src/mem2.c | 528 - .../Pods/WCDBOptimizedSQLCipher/src/mem3.c | 687 - .../Pods/WCDBOptimizedSQLCipher/src/mem5.c | 576 - .../WCDBOptimizedSQLCipher/src/memjournal.c | 434 - .../Pods/WCDBOptimizedSQLCipher/src/msvc.h | 36 - .../Pods/WCDBOptimizedSQLCipher/src/mutex.c | 360 - .../Pods/WCDBOptimizedSQLCipher/src/mutex.h | 70 - .../WCDBOptimizedSQLCipher/src/mutex_noop.c | 215 - .../WCDBOptimizedSQLCipher/src/mutex_unix.c | 429 - .../WCDBOptimizedSQLCipher/src/mutex_wcdb.c | 116 - .../WCDBOptimizedSQLCipher/src/mutex_wcdb.h | 53 - .../Pods/WCDBOptimizedSQLCipher/src/notify.c | 332 - Example/Pods/WCDBOptimizedSQLCipher/src/os.c | 423 - Example/Pods/WCDBOptimizedSQLCipher/src/os.h | 217 - .../WCDBOptimizedSQLCipher/src/os_common.h | 105 - .../WCDBOptimizedSQLCipher/src/os_setup.h | 57 - .../Pods/WCDBOptimizedSQLCipher/src/os_unix.c | 8047 ------ .../Pods/WCDBOptimizedSQLCipher/src/os_wcdb.c | 224 - .../Pods/WCDBOptimizedSQLCipher/src/os_wcdb.h | 67 - .../Pods/WCDBOptimizedSQLCipher/src/pager.c | 7767 ------ .../Pods/WCDBOptimizedSQLCipher/src/pager.h | 256 - .../Pods/WCDBOptimizedSQLCipher/src/pcache.c | 890 - .../Pods/WCDBOptimizedSQLCipher/src/pcache.h | 194 - .../Pods/WCDBOptimizedSQLCipher/src/pcache1.c | 1276 - .../Pods/WCDBOptimizedSQLCipher/src/pragma.c | 2510 -- .../Pods/WCDBOptimizedSQLCipher/src/pragma.h | 670 - .../Pods/WCDBOptimizedSQLCipher/src/prepare.c | 929 - .../Pods/WCDBOptimizedSQLCipher/src/printf.c | 1280 - .../Pods/WCDBOptimizedSQLCipher/src/queue.c | 114 - .../Pods/WCDBOptimizedSQLCipher/src/queue.h | 48 - .../Pods/WCDBOptimizedSQLCipher/src/random.c | 134 - .../Pods/WCDBOptimizedSQLCipher/src/resolve.c | 1761 -- .../Pods/WCDBOptimizedSQLCipher/src/rowset.c | 502 - .../Pods/WCDBOptimizedSQLCipher/src/select.c | 6619 ----- .../WCDBOptimizedSQLCipher/src/sqlcipher.h | 83 - .../WCDBOptimizedSQLCipher/src/sqlite3ext.h | 671 - .../WCDBOptimizedSQLCipher/src/sqliteInt.h | 4660 ---- .../WCDBOptimizedSQLCipher/src/sqliteLimit.h | 211 - .../Pods/WCDBOptimizedSQLCipher/src/status.c | 380 - .../Pods/WCDBOptimizedSQLCipher/src/table.c | 198 - .../Pods/WCDBOptimizedSQLCipher/src/threads.c | 274 - .../WCDBOptimizedSQLCipher/src/tokenize.c | 858 - .../WCDBOptimizedSQLCipher/src/treeview.c | 689 - .../Pods/WCDBOptimizedSQLCipher/src/trigger.c | 1186 - .../Pods/WCDBOptimizedSQLCipher/src/update.c | 989 - .../Pods/WCDBOptimizedSQLCipher/src/upsert.c | 252 - Example/Pods/WCDBOptimizedSQLCipher/src/utf.c | 532 - .../Pods/WCDBOptimizedSQLCipher/src/util.c | 1629 -- .../Pods/WCDBOptimizedSQLCipher/src/vacuum.c | 408 - .../Pods/WCDBOptimizedSQLCipher/src/vdbe.c | 7619 ------ .../Pods/WCDBOptimizedSQLCipher/src/vdbe.h | 386 - .../Pods/WCDBOptimizedSQLCipher/src/vdbeInt.h | 607 - .../Pods/WCDBOptimizedSQLCipher/src/vdbeapi.c | 1978 -- .../Pods/WCDBOptimizedSQLCipher/src/vdbeaux.c | 4974 ---- .../WCDBOptimizedSQLCipher/src/vdbeblob.c | 507 - .../Pods/WCDBOptimizedSQLCipher/src/vdbemem.c | 1891 -- .../WCDBOptimizedSQLCipher/src/vdbesort.c | 2755 -- .../WCDBOptimizedSQLCipher/src/vdbetrace.c | 194 - .../Pods/WCDBOptimizedSQLCipher/src/vtab.c | 1247 - .../Pods/WCDBOptimizedSQLCipher/src/vxworks.h | 32 - Example/Pods/WCDBOptimizedSQLCipher/src/wal.c | 3852 --- Example/Pods/WCDBOptimizedSQLCipher/src/wal.h | 150 - .../Pods/WCDBOptimizedSQLCipher/src/walker.c | 190 - .../Pods/WCDBOptimizedSQLCipher/src/where.c | 5371 ---- .../WCDBOptimizedSQLCipher/src/whereInt.h | 586 - .../WCDBOptimizedSQLCipher/src/wherecode.c | 2241 -- .../WCDBOptimizedSQLCipher/src/whereexpr.c | 1598 -- .../Pods/WCDBOptimizedSQLCipher/src/window.c | 2256 -- .../SmartCodable.xcodeproj/project.pbxproj | 430 +- .../BaseCompatibilityViewController.swift | 7 + .../Base/BaseViewController.swift | 1 + .../IntroduceViewController.swift" | 3 +- .../Introduce_10ViewController.swift" | 1 + .../Introduce_11ViewController.swift" | 43 + .../Introduce_1ViewController.swift" | 14 +- .../Introduce_2ViewController.swift" | 12 +- .../Introduce_8ViewController.swift" | 14 +- .../MixDecodingViewController.swift" | 68 +- .../CustomDecodingValueViewContriller.swift" | 21 +- .../BeforeDecodingViewController.swift" | 30 +- .../ConcurrenceLogViewController.swift" | 79 + .../DecodingArrayLogViewController.swift" | 18 +- .../ComplexDataStructureModel.swift" | 2 - .../SmartCodable/Test2ViewController.swift | 275 +- .../SmartCodable/Test3ViewController.swift | 39 +- Example/SmartCodable/TestViewController.swift | 51 +- Example/SmartCodable/ViewController.swift | 11 +- .../ReplaceHandyJSON_6ViewController.swift" | 1 - .../CaseFive_wcdbViewController.swift" | 42 - .../CaseFour_KeyStrategyViewController.swift" | 173 - ...aseFour_OptionalModelViewController.swift" | 60 - .../CaseOne/CaseOne_IntViewController.swift" | 52 - .../CaseThree_ArrViewController.swift" | 46 - .../CaseThree_DictViewController.swift" | 49 - .../CaseThree_URLViewController.swift" | 49 - .../Encode_BaseData_BoolViewController.swift" | 76 + .../Encode_BaseData_FloatiewController.swift" | 65 + .../Encode_BaseData_IntViewController.swift" | 65 + ...ncode_BaseData_StringViewController.swift" | 70 + .../Encode_ContainerViewcontroller.swift" | 9 + .../Encode_CustomKeyViewController.swift" | 64 + .../Encode_IgnoredKeyViewController.swift" | 62 + ...ncode_SpecialData_anyViewController.swift" | 94 + ...ode_SpecialData_colorViewController.swift" | 49 + ...code_SpecialData_dataViewController.swift" | 47 + ...code_SpecialData_dateViewController.swift" | 50 + ...code_SpecialData_enumViewController.swift" | 111 + ...ode_SpecialData_modelViewController.swift" | 95 + ...ncode_SpecialData_urlViewController.swift" | 47 + .../TestEncodeCaseViewController.swift" | 164 + .../TestCaseViewController.swift" | 86 +- .../BaseData_BoolViewController.swift" | 6 +- .../BaseData_DateViewController.swift" | 57 + .../BaseData_FloatViewController.swift" | 4 +- .../BaseData_Int8ViewController.swift" | 57 + .../BaseData_IntViewController.swift" | 56 + .../BaseData_StringViewController.swift" | 8 +- .../CaseFive_concurrenceViewController.swift" | 0 ...ontainer_ArrayKeylessViewController.swift" | 14 +- ...tainer_ArrayNestArrayViewController.swift" | 8 +- ...ntainer_ArrayNestDictViewController.swift" | 10 +- .../Container_ArrayNullViewController.swift" | 8 +- ...ner_ArrayTypeMismatchViewController.swift" | 12 +- .../Arr/Container_ArrayViewController.swift" | 51 + ...Container_DictKeylessViewController.swift" | 9 +- ...ntainer_DictNestArrayViewController.swift" | 13 +- ...ontainer_DictNestDictViewController.swift" | 8 +- .../Container_DictNullViewController.swift" | 8 +- ...iner_DictTypeMismatchViewController.swift" | 8 +- .../Dict/Container_DictViewController.swift" | 81 + ...ing_globalKeyStrategyViewController.swift" | 109 + .../Decoding_keyIgnoreViewController.swift" | 69 + .../Key/Decoding_keyMapViewController.swift" | 76 + ...g_globalValueStrategyViewController.swift" | 66 + .../Decoding_valueMapViewController.swift" | 105 + .../SpecialData_ColorViewController.swift" | 43 + .../SpecialData_EnumViewController.swift" | 9 +- .../SpecialData_FloatViewController.swift" | 7 +- .../SpecialData_SmartAnyViewController.swift" | 99 + .../SpecialData_URLViewController.swift" | 74 + .../SpecialData_dataViewController.swift" | 8 +- .../SpecialData_dateViewController.swift" | 32 +- .../Support_JSONStringViewController.swift" | 16 +- ...port_didFinishMappingViewController.swift" | 22 +- ...7\264\346\230\216\344\277\241\346\201\257" | 10 +- Example/Tests/PerformanceTest.swift | 4 +- Example/Tests/Tests.swift | 4 +- Package.swift | 2 +- README-EN.md | 425 - README.md | 624 +- SmartCodable.podspec | 7 +- SmartCodable/Classes/Cache/Cachable.swift | 57 + .../DecodingProcessCoordinator.swift | 20 - .../Container/SmartCodingKey.swift | 37 - ...artJSONKeyedDecodingContainer+decode.swift | 276 - ...yedDecodingContainer+decodeIfPresent.swift | 194 - .../SmartJSONKeyedDecodingContainer.swift | 130 - ...rtSONUnkeyedDecodingContainer+decode.swift | 110 - .../SmartSONUnkeyedDecodingContainer.swift | 137 - ...Decoder+SingleValueDecodingContainer.swift | 151 - ...alModelCache.swift => DecodingCache.swift} | 31 +- .../DecodingError+Extension.swift | 6 + .../JSONDecoder/Decoder/IgnoredKey.swift | 35 + .../Impl/JSONDecoderImpl+KeyedContainer.swift | 546 + ...JSONDecoderImpl+SingleValueContainer.swift | 240 + .../JSONDecoderImpl+UnkeyedContainer.swift | 429 + .../Decoder/Impl/JSONDecoderImpl+unwrap.swift | 385 + .../Decoder/Impl/JSONDecoderImpl.swift | 144 + ...{ModelKeyMapper.swift => KeysMapper.swift} | 40 +- .../Decoder/SmartJSONDecoder.swift | 47 +- .../Decoder/SmartJSONDecodingStorage.swift | 44 - .../Decoder/_SmartJSONDecoder+Unbox.swift | 615 - .../Decoder/_SmartJSONDecoder.swift | 73 - .../Patcher/Patcher+Provider.swift | 6 +- .../Patcher/Patcher+Transformer.swift | 12 +- .../JSONKeyedEncodingContainer.swift | 192 + .../JSONSingleValueEncodingContainer.swift | 108 + .../JSONUnkeyedEncodingContainer.swift | 133 + .../Classes/JSONEncoder/EncodingCache.swift | 82 + .../JSONEncoder/Impl/JSONEncoderImpl.swift | 100 + .../Impl/_SpecialTreatmentEncoder.swift | 166 + .../Classes/JSONEncoder/JSONFuture.swift | 127 + .../JSONEncoder/SmartJSONEncoder.swift | 261 + .../Classes/JSONValue/JSONParser.swift | 643 + .../JSONValue/JSONValue+Extension.swift | 66 + .../Classes/JSONValue/JSONValue.swift | 407 + SmartCodable/Classes/Log/LogCache.swift | 91 +- SmartCodable/Classes/Log/LogContainer.swift | 4 +- SmartCodable/Classes/Log/LogItem.swift | 8 +- SmartCodable/Classes/Log/SafeDictionary.swift | 66 + SmartCodable/Classes/Log/SmartLog.swift | 84 +- .../Classes/SmartCodable/IgnoredKey.swift | 46 - .../Classes/SmartCodable/SmartCodable.swift | 4 + .../Classes/SmartCodable/SmartDecodable.swift | 2 + .../Classes/SmartCodable/SmartEncodable.swift | 15 +- .../Classes/SmartCodable/SmartUpdater.swift | 88 + .../SmartAny.swift | 15 +- .../SmartCaseDefaultable.swift | 11 +- .../Classes/SmartType/SmartColor.swift | 66 + .../Transformer/ColorTransformer.swift | 64 +- .../Classes/Transformer/DataTransformer.swift | 9 +- .../Classes/Transformer/DateTransformer.swift | 22 +- .../Classes/Transformer/Transformer.swift | 4 +- .../Classes/Transformer/URLTransformer.swift | 9 +- SmartCodable/file.swift | 9 - 476 files changed, 9232 insertions(+), 237862 deletions(-) create mode 100644 Document/README/CompareWithHandyJSON.md create mode 100644 Document/README/LearnMore.md create mode 100644 Document/README/Usages.md create mode 100644 "Document/SmartCodable\346\211\247\350\241\214\351\200\273\350\276\221.md" create mode 100644 Document/TestCaseSpecification.xmind delete mode 100644 Example/Pods/SQLiteRepairKit/LICENSE delete mode 100644 Example/Pods/SQLiteRepairKit/README.md delete mode 100644 Example/Pods/SQLiteRepairKit/repair/SQLiteRepairKit.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_api.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_column.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_column.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_os.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_os.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_output.cpp delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_util.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_util.h delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_values.c delete mode 100644 Example/Pods/SQLiteRepairKit/repair/sqliterk_values.h delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-dummy.m delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-umbrella.h delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.debug.xcconfig delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap delete mode 100644 Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.release.xcconfig rename Example/Pods/Target Support Files/{SQLiteRepairKit/SQLiteRepairKit-Info.plist => SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist} (80%) delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-Info.plist delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-dummy.m delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-prefix.pch delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-umbrella.h delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.debug.xcconfig delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.modulemap delete mode 100644 Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.release.xcconfig delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-dummy.m delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-umbrella.h delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.debug.xcconfig delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap delete mode 100644 Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.release.xcconfig delete mode 100644 Example/Pods/WCDB.swift/LICENSE delete mode 100644 Example/Pods/WCDB.swift/README.md delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Column.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ColumnDef.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ColumnIndex.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ColumnResult.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ColumnType.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Conflict.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Convertible.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Describable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Expression.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ForeignKey.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/FundamentalValue.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Handle.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/HandleStatement.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/JoinClause.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/LiteralValue.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/ModuleArgument.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Operable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Order.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/OrderTerm.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Pragma.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Statement.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementAlterTable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementAttach.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateIndex.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateTable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateVirtualTable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementDelete.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementDetach.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementDropIndex.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementDropTable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementExplain.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementInsert.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementPragma.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementReindex.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementRelease.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementRollback.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementSavepoint.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementSelect.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementTransaction.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementUpdate.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/StatementVacuum.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Subquery.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/TableConstraint.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Tokenize.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/abstract/Tracer.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/builtin/CodableType.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/builtin/CommonStatement.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/builtin/Master.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/Config.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/Core.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/CoreStatement.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/Database.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/HandlePool.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/RecyclableCore.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/base/Transaction.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/ColumnConstraintBinding.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/IndexBinding.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/Property.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/Redirectable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/TableBinding.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/TableConstraintBinding.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/binding/VirtualTableBinding.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/CodingTableKey.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/ColumnCodable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/ColumnTypeDecoder.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/TableCodable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/TableDecoder.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/codable/TableEncoder.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/fts/WCDBTokenize.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/ChainCall.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Declare.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Delete.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Insert.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Interface.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/MultiSelect.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/RowSelect.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Select.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Selectable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Table.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/TableInterface.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/core/interface/Update.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Atomic.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/ConcurrentList.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Convenience.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Error.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/File.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Lock.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Optional.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/RWLock.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Recyclable.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.c delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.h delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/SteadyClock.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/Tagged.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/ThreadLocal.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/TimedQueue.swift delete mode 100644 Example/Pods/WCDB.swift/swift/source/util/WCDB-Bridging.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/LICENSE delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/README.md delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3Int.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_aux.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_expr.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_icu.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_porter.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_snippet.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenize_vtab.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer1.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode2.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_write.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/icu/icu.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/icu/sqliteicu.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/rbu/sqlite3rbu.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/rbu/sqlite3rbu.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/rtree/rtree.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/rtree/rtree.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/rtree/sqlite3rtree.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/userauth/sqlite3userauth.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/ext/userauth/userauth.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/fts5.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/fts5.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/keywordhash.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/opcodes.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/opcodes.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/parse.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/parse.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/sqlite3.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/alter.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/analyze.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/attach.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/auth.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/backup.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/bitvec.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/btmutex.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/btree.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/btree.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/btreeInt.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/build.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/callback.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/complete.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/crypto.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/crypto.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/crypto_cc.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/crypto_impl.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/crypto_libtomcrypt.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/ctime.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/date.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/dbstat.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/delete.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/expr.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/fault.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/fkey.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/func.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/global.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/hash.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/hash.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/hwtime.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/insert.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/legacy.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/loadext.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/main.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/malloc.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mem0.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mem1.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mem2.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mem3.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mem5.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/memjournal.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/msvc.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex_noop.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex_unix.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex_wcdb.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/mutex_wcdb.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/notify.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os_common.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os_setup.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os_unix.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os_wcdb.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/os_wcdb.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pager.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pager.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pcache.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pcache.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pcache1.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pragma.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/pragma.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/prepare.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/printf.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/queue.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/queue.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/random.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/resolve.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/rowset.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/select.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/sqlcipher.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/sqlite3ext.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/sqliteInt.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/sqliteLimit.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/status.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/table.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/threads.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/tokenize.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/treeview.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/trigger.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/update.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/upsert.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/utf.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/util.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vacuum.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbe.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbe.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbeInt.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbeapi.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbeaux.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbeblob.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbemem.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbesort.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vdbetrace.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vtab.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/vxworks.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/wal.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/wal.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/walker.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/where.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/whereInt.h delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/wherecode.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/whereexpr.c delete mode 100644 Example/Pods/WCDBOptimizedSQLCipher/src/window.c create mode 100644 "Example/SmartCodable/Smart/1.Introduce(\344\275\277\347\224\250\344\273\213\347\273\215)/Introduce_11ViewController.swift" create mode 100644 "Example/SmartCodable/Smart/3.SmartLog(\350\260\203\350\257\225\346\227\245\345\277\227)/ConcurrenceLogViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFive/CaseFive_wcdbViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFour/CaseFour_KeyStrategyViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFour/CaseFour_OptionalModelViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_IntViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_ArrViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_DictViewController.swift" delete mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_URLViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/BaseData/Encode_BaseData_BoolViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/BaseData/Encode_BaseData_FloatiewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/BaseData/Encode_BaseData_IntViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/BaseData/Encode_BaseData_StringViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/Container/Encode_ContainerViewcontroller.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/CustomKey/Encode_CustomKeyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/CustomKey/Encode_IgnoredKeyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_anyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_colorViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_dataViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_dateViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_enumViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_modelViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/SpecialData/Encode_SpecialData_urlViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\347\274\226\347\240\201/TestEncodeCaseViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/TestCaseViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/TestCaseViewController.swift" (51%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_BoolViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_BoolViewController.swift" (95%) create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_DateViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_FloatViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_FloatViewController.swift" (93%) create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_Int8ViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_IntViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_StringViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/BaseData/BaseData_StringViewController.swift" (86%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFive/CaseFive_concurrenceViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFive/CaseFive_concurrenceViewController.swift" (100%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_ArrayKeylessViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayKeylessViewController.swift" (53%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseTwo/CaseTwo_ArrayNestArrayViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayNestArrayViewController.swift" (82%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseTwo/CaseTwo_ArrayNestDictViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayNestDictViewController.swift" (87%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_ArrayNullViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayNullViewController.swift" (71%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_ArrayTypeMismatchViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayTypeMismatchViewController.swift" (67%) create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Arr/Container_ArrayViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_DictKeylessViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictKeylessViewController.swift" (93%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseTwo/CaseTwo_DictNestArrayViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictNestArrayViewController.swift" (85%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseTwo/CaseTwo_DictNestDictViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictNestDictViewController.swift" (84%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_DictNullViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictNullViewController.swift" (95%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseOne/CaseOne_DictTypeMismatchViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictTypeMismatchViewController.swift" (93%) create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Container/Dict/Container_DictViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Decoding/Key/Decoding_globalKeyStrategyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Decoding/Key/Decoding_keyIgnoreViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Decoding/Key/Decoding_keyMapViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Decoding/Value/Decoding_globalValueStrategyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Decoding/Value/Decoding_valueMapViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_ColorViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_EnumViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_EnumViewController.swift" (78%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_FloatViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_FloatViewController.swift" (85%) create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_SmartAnyViewController.swift" create mode 100644 "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_URLViewController.swift" rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_dataViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_dataViewController.swift" (93%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThree_dateViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/SpecialData/SpecialData_dateViewController.swift" (79%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseThree/CaseThreeJSONStringViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Support/Support_JSONStringViewController.swift" (68%) rename "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\346\225\260\346\215\256\346\265\213\350\257\225/CaseFour/CaseFour_didFinishMappingViewController.swift" => "Example/SmartCodable/\346\265\213\350\257\225\347\224\250\344\276\213/\350\247\243\347\240\201/\346\225\260\346\215\256\346\265\213\350\257\225/Support/Support_didFinishMappingViewController.swift" (88%) delete mode 100644 README-EN.md create mode 100644 SmartCodable/Classes/Cache/Cachable.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/DecodingProcessCoordinator.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartCodingKey.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartJSONKeyedDecodingContainer+decode.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartJSONKeyedDecodingContainer+decodeIfPresent.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartJSONKeyedDecodingContainer.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartSONUnkeyedDecodingContainer+decode.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/SmartSONUnkeyedDecodingContainer.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Container/_SmartJSONDecoder+SingleValueDecodingContainer.swift rename SmartCodable/Classes/JSONDecoder/Decoder/{InitialModelCache.swift => DecodingCache.swift} (81%) rename SmartCodable/Classes/JSONDecoder/{Container => Decoder}/DecodingError+Extension.swift (88%) create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/IgnoredKey.swift create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/Impl/JSONDecoderImpl+KeyedContainer.swift create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/Impl/JSONDecoderImpl+SingleValueContainer.swift create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/Impl/JSONDecoderImpl+UnkeyedContainer.swift create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/Impl/JSONDecoderImpl+unwrap.swift create mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/Impl/JSONDecoderImpl.swift rename SmartCodable/Classes/JSONDecoder/Decoder/{ModelKeyMapper.swift => KeysMapper.swift} (73%) delete mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/SmartJSONDecodingStorage.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/_SmartJSONDecoder+Unbox.swift delete mode 100644 SmartCodable/Classes/JSONDecoder/Decoder/_SmartJSONDecoder.swift create mode 100644 SmartCodable/Classes/JSONEncoder/Container/JSONKeyedEncodingContainer.swift create mode 100644 SmartCodable/Classes/JSONEncoder/Container/JSONSingleValueEncodingContainer.swift create mode 100644 SmartCodable/Classes/JSONEncoder/Container/JSONUnkeyedEncodingContainer.swift create mode 100644 SmartCodable/Classes/JSONEncoder/EncodingCache.swift create mode 100644 SmartCodable/Classes/JSONEncoder/Impl/JSONEncoderImpl.swift create mode 100644 SmartCodable/Classes/JSONEncoder/Impl/_SpecialTreatmentEncoder.swift create mode 100644 SmartCodable/Classes/JSONEncoder/JSONFuture.swift create mode 100644 SmartCodable/Classes/JSONEncoder/SmartJSONEncoder.swift create mode 100644 SmartCodable/Classes/JSONValue/JSONParser.swift create mode 100644 SmartCodable/Classes/JSONValue/JSONValue+Extension.swift create mode 100644 SmartCodable/Classes/JSONValue/JSONValue.swift create mode 100644 SmartCodable/Classes/Log/SafeDictionary.swift delete mode 100644 SmartCodable/Classes/SmartCodable/IgnoredKey.swift create mode 100644 SmartCodable/Classes/SmartCodable/SmartUpdater.swift rename SmartCodable/Classes/{SmartCodable => SmartType}/SmartAny.swift (94%) rename SmartCodable/Classes/{SmartCodable => SmartType}/SmartCaseDefaultable.swift (80%) create mode 100644 SmartCodable/Classes/SmartType/SmartColor.swift delete mode 100644 SmartCodable/file.swift diff --git a/Document/README/CompareWithHandyJSON.md b/Document/README/CompareWithHandyJSON.md new file mode 100644 index 00000000..671915d5 --- /dev/null +++ b/Document/README/CompareWithHandyJSON.md @@ -0,0 +1,47 @@ +# SmartCodable - Compare With HandyJSON + +| 序号 | 🎯 特性 | 💬 特性说明 💬 | SmartCodable | HandyJSON | +| ---- | ----------------------------- | ------------------------------------------------------------ | ------------ | --------- | +| 1 | **强大的兼容性** | 完美兼容:**字段缺失** & **字段值为nul** & **字段类型错误** | ✅ | ✅ | +| 2 | **类型自适应** | 如JSON中是一个Int,但对应Model是String字段,会自动完成转化 | ✅ | ✅ | +| 3 | **解析Any** | 支持解析 **[Any], [String: Any]** 等类型 | ✅ | ✅ | +| 4 | **解码回调** | 支持Model解码完成的回调,即:**didFinishingMapping** | ✅ | ✅ | +| 5 | **属性初始化值填充** | 当解析失败时,支持使用初始的Model属性的赋值。 | ✅ | ✅ | +| 6 | **字符串的Model化** | 字符串是json字符串,支持进行Model化解析 | ✅ | ✅ | +| 7 | **枚举的解析** | 当枚举解析失败时,支持兼容。 | ✅ | ✅ | +| 8 | **属性的自定义解析** - 重命名 | 自定义解码key(对解码的Model属性重命名) | ✅ | ✅ | +| 9 | **属性的自定义解析** - 忽略 | 忽略某个Model属性的解码 | ✅ | ✅ | +| 10 | **支持designatedPath** | 实现自定义解析路径 | ✅ | ✅ | +| 11 | **Model的继承** | 在model的继承关系下,Codable的支持力度较弱,使用不便(可以支持) | ❌ | ✅ | +| 12 | **自定义解析路径** | 指定从json的层级开始解析 | ✅ | ✅ | +| 13 | **超复杂的数据解码** | 解码过程中,多数据做进一步的整合/处理。如: 数据的扁平化处理 | ✅ | ⚠️ | +| 14 | **解码性能** | 在解码性能上,SmartCodable 平均强 30% | ✅ | ⚠️ | +| 15 | **异常解码日志** | 当解码异常进行了兼容处理时,提供排查日志 | ✅ | ❌ | +| 16 | **安全性方面** | 底层实现的稳定性和安全性。 | ✅ | ❌ | + +整体来讲: SmartCodable 和 HandyJSON 相比,在功能和使用上相近。 + + +#### 安全性 & 稳定性 + +* **HandyJSON** 使用Swift的反射特性来实现数据的序列化和反序列化。**该机制是非法的,不安全的**, 更多的细节请访问 **[HandyJSON 的466号issue](https://github.com/alibaba/HandyJSON/issues/466)**. + +* **Codable** 是Swift标准库的一部分,提供了一种声明式的方式来进行序列化和反序列化,它更为通用。 + + + +## 使用SmartCodable 平替 HandyJSON + +更多内容请查看: [替换指导](https://github.com/intsig171/SmartCodable/blob/develop/Document/Suggest/suggest4.md) + +| 内容项 | 内容项说明 | 使用场景 | 替换难度 | 评判理由 | +| --------------- | --------------------------------------------- | -------- | -------- | ------------------------------------------------------ | +| ①声明Model | 声明Model | ★★★★★ | ★☆☆☆☆ | 全局将 HandyJSON 替换为 SmartCodable即可。 | +| ②反序列化 | 数据的模型化(数据转Model) | ★★★★★ | ☆☆☆☆☆ | 完全一样的调用方式,无需处理。 | +| ③序列化 | 模型的数据化(Model转数据) | ★☆☆☆☆ | ★☆☆☆☆ | 将 `toJSON()` 替换为 `toDictionary()` 或 `toArray()`。 | +| ④解码完成的回调 | 解析完成进一步处理数据 | ★★☆☆☆ | ☆☆☆☆☆ | 完全一样的调用方式,无需处理。 | +| ⑤自定义解析Key | 忽略key的解析 & 自定义Key的映射关系 | ★★★☆☆ | ★★★☆☆ | 需要更改调用方式。 | +| ⑥解析Any | 解析Any类型的数据。Any,[String: Any], [Any] | ★☆☆☆☆ | ★☆☆☆☆ | 将Any替换为SmartAny | +| ⑦处理继承关系 | 解析存在的继承关系的Model | ★☆☆☆☆ | ★★★★★ | 建议使用协议实现。 | +| ⑧枚举的解析 | 解析枚举属性 | ★☆☆☆☆ | ★☆☆☆☆ | 多实现一个 defaultCase | + diff --git a/Document/README/LearnMore.md b/Document/README/LearnMore.md new file mode 100644 index 00000000..d7abc77c --- /dev/null +++ b/Document/README/LearnMore.md @@ -0,0 +1,38 @@ +# FAQ + + + +### Responses to questions + +| 💡 questions | answers | +| ----------------------------------- | ------------------------------------------------------------ | +| 1 在mapping方法中支持解析忽略 | [不采纳的理由](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest1.md) | +| 2 像HandyJSON一样支持继承关系的解析 | [不采纳的理由](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest2.md) | +| 3 支持初始值填充 | [实现逻辑](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest3.md) | +| 4 提供HandyJSON的替换指导 | [替换指导](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest4.md) | +| 5 提供全局的Key映射策略 | [实现逻辑](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest5.md) | +| 6 支持UIColor的解析 | [实现逻辑](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest6.md) | +| 7 增加单个Value的自定义转换策略 | [实现逻辑](https://github.com/intsig171/SmartCodable/blob/main/Document/Suggest/suggest7.md) | + + + + + + + +### About Codable + +这是Swift数据解析方案的系列文章: + +[Swift数据解析(第一篇) - 技术选型](https://juejin.cn/post/7288517000581070902) + +[Swift数据解析(第二篇) - Codable 上](https://juejin.cn/post/7288517000581087286) + +[Swift数据解析(第二篇) - Codable 下](https://juejin.cn/post/7288517000581120054) + +[Swift数据解析(第三篇) - Codable源码学习](https://juejin.cn/post/7288504491506090023) + +[Swift数据解析(第四篇) - SmartCodable 上](https://juejin.cn/post/7288513881735151670) + +[Swift数据解析(第四篇) - SmartCodable 下](https://juejin.cn/post/7288517000581169206) + diff --git a/Document/README/Usages.md b/Document/README/Usages.md new file mode 100644 index 00000000..57f0cb5f --- /dev/null +++ b/Document/README/Usages.md @@ -0,0 +1,525 @@ +## Usages + +### 1. Decoding dictionary(解码字典) + +``` +import SmartCodable + +struct Model: SmartCodable { + var name: String = "" +} + +let dict: [String: String] = ["name": "xiaoming"] +guard let model = Model.deserialize(from: dict) else { return } +``` + + + +### 2. Decode array(解码数组) + +``` +import SmartCodable + +struct Model: SmartCodable { + var name: String = "" +} + +let dict: [String: String] = ["name": "xiaoming"] +let arr = [dict, dict] +guard let models = [Model].deserialize(from: arr) else { return } +``` + + + +### 3. Serialization(序列化) + +``` +// to model +guard let xiaoMing = JsonToModel.deserialize(from: dict) else { return } + +// to dict +let studentDict = xiaoMing.toDictionary() ?? [:] + +// to json +let json1 = xiaoMing.toJSONString(prettyPrint: false) ?? "" +``` + + + +### 4. designatedPath (指定的路径) + +SmartCoable supports deserialization from designated path of JSON. + +SmartCoable支持从指定路径的JSON进行反序列化。 + +``` +let jsonString = """ + { + "people": [ + { + "name": "John Doe", + "age": 30 + }, + { + "name": "Jane Smith", + "age": 25 + } + ] + } +""" + +struct PathModel: SmartCodable { + var name: String? + var age: Int? +} + +if let models = [PathModel].deserialize(from: jsonString, designatedPath: "people") { + print(models) +} +``` + + + +### 5. Composition Object(组成对象) + +Notice that all the properties of a class/struct need to deserialized should be type conformed to `SmartCodable`. + +注意,类/结构体中所有需要反序列化的属性都应该符合 `SmartCodable`。 + +``` +struct Model: SmartCodable { + var name: String = "Mccc" + var sub: SubModel? +} +struct SubModel: SmartCodable { + var name: String = "" +} +``` + + + +## Custom decoding types(自定义的解析类型) + +### 1. Decoding Any(解码Any) + +Codable does not decode the Any type, meaning that the attribute type of the model cannot be **Any**, **[Any]** and **[String: Any]**. + +**SmartAny** is a solution to Any provided by **SmartCodable**. + +Codable是无法解码Any类型的,意味着模型的属性类型不可以是 **Any**,**[Any]**,**[String: Any]**等类型。**SmartCodable** 提供了 **SmartAny** 替代 **Any**。 + +``` +struct AnyModel: SmartCodable { + var name: SmartAny? + var dict: [String: SmartAny] = [:] + var arr: [SmartAny] = [] +} +``` + +``` +let dict = [ + "name": "xiao ming", + "age": 20, + "dict": inDict, + "arr": arr +] as [String : Any] + +guard let model = AnyModel.deserialize(from: dict) else { return } +``` + +The real data is wrapped in SmartAny, you need to use **peel** to convert SmartAny to Any. + +真实的数据被 SmartAny 包裹住了,需要使用 **peel** 将SmartAny 转 成Any。 + +``` +print(model.name.peel ) +print(model.dict.peel) +print(model.arr.peel) +``` + + **To SmartAny** (Pay attention to it if you need to) + +| From | To | Example | +| ---------------- | -------------------- | ---------------------------- | +| `Any` | `SmartAny` | `SmartAny(from: "some")` | +| `[Any]` | `[SmartAny]` | `[["key3": "value3"]].cover` | +| `[String: Any] ` | `[String: SmartAny]` | `["key2": "value2"].cover` | + + + +### 2.Modeling of json strings(json字符串的模型化) + +``` +let dict: [String: Any] = [ + "hobby": "{\"name\":\"sleep\"}", +] +guard let model = Model.deserialize(from: dict) else { return } +print(model) + +struct Model: SmartCodable { + var hobby: Hobby? +} + +struct Hobby: SmartCodable { + var name: String = "" +} +``` + + + +### 3. Decoding UIColor(解析UIColor) + +Use SmartColor instead of UIColor. + +``` +let dict = [ + "color": "7DA5E3" +] + +struct Model: SmartCodable { + var color: SmartColor? +} + +guard let model = Model.deserialize(from: dict) else { return } +print(model.color?.peel) +``` + +> **UIColor** 是 `non-final class`。非最终类不能简单地实现`Codable`的`init(from:)`。 + + + +### 4. Decoding enum(解码枚举) + +Make the enumeration follow **SmartCaseDefaultable**. + +让枚举遵循 **SmartCaseDefaultable**。 + +``` +struct CompatibleEnum: SmartCodable { + var enumTest: TestEnum? +} + +enum TestEnum: String, SmartCaseDefaultable { + case a + case b + case c = "hello" +} +``` + +#### Decoding of associative value enum(支持关联值枚举的解码) + +Make the enumeration follow **SmartAssociatedEnumerable**。Override the **mappingForValue** method and take over the decoding process yourself. + +让枚举遵循 **SmartAssociatedEnumerable**,重写mappingForValue方法,你自己接管解码过程。 + +``` +enum Sex: SmartAssociatedEnumerable { + case man + case women + case other(String) +} +struct CompatibleEnum: SmartCodable { + var sex: Sex = .man + static func mappingForValue() -> [SmartValueTransformer]? { + [ + CodingKeys.sex <--- RelationEnumTranformer() + ] + } +} + +struct RelationEnumTranformer: ValueTransformable { + typealias Object = Sex + typealias JSON = String + + func transformToJSON(_ value: Introduce_8ViewController.Sex?) -> String? { + // do something + } + + func transformFromJSON(_ value: Any?) -> Sex? { + // do something + } +} +``` + + + +## Compatibility(兼容性) + +If attribute resolution fails, SmartCodable performs compatibility processing for thrown exceptions. Ensure that the entire parsing is not interrupted. Even better, you don't have to do anything about it. + +某个属性解析失败时候,SmartCodable会接管抛出的异常,进行兼容性处理。确保整个解析不会被中断。更好的是不需要你为此做任何事情。 + +``` +let dict = [ + "number1": "123", + "number2": "Mccc", + "number3": "Mccc" +] + +struct Model: SmartCodable { + var number1: Int? + var number2: Int? + var number3: Int = 1 +} + +// decode result +// Model(number1: 123, number2: nil, number3: 1) +``` + + + +### Type conversion compatibility(类型转化的兼容) + +When the data is parsed, the type cannot be matched. Raises a.typeMismatch error. SmartCodable will attempt to convert data of type String to the desired type Int. + +当对该数据进行解析时,由于不能匹配类型。会抛出`.typeMismatch` error。SmartCodable 会尝试将 String类型的数据 转换为 所需的 Int 类型数据。 + +### Default Fill compatible(使用填充值的兼容) + +When the type conversion fails, the initialization value of the currently parsed property is retrieved for padding. + +当类型转换失时,会获取当前解析的属性的初始化值进行填充。 + + + +## User-defined Key when decoding(自定义Key) + +### 1. Ignore key parsing(忽略key的解析) + +``` +struct Model: SmartCodable { + var name: String = "" + var ignore: String = "" + var age: Int = 0 + + enum CodingKeys: String, CodingKey { + case name + case age + } +} +``` + +If you don't want **ignore** to participate in parsing, delete it in **CodingKeys** and you'll be left with parsing. But with SmartCodable, you can use @IgnoredKey. + +如果你不希望 **ignore** 参与解析,就在 **CodingKeys** 中删除它,留下的就是参与解析的。但有了 `SmartCodable` ,你就可以使用 `@IgnoredKey` . + +``` +struct Home: SmartCodable { + var name: String = "" + @IgnoredKey + var age: [Any] = ["1"] + @IgnoredKey + var area: String = "area" +} +``` + + + +### 2. Rename Key when decoding(key的重命名) + +``` +public enum SmartKeyDecodingStrategy : Sendable { + case useDefaultKeys + + // 蛇形命名转驼峰命名 + case fromSnakeCase + + // 首字母大写转小写 + case firstLetterLower + + // 首字母小写转大写 + case firstLetterUpper +} +``` + +``` +let option1: SmartDecodingOption = .key(.fromSnakeCase) +guard let model1 = TwoModel.deserialize(from: dict1, options: [option1]) else { return } +``` + + + +If you only need to change the mapping rules of a Model Key, you can override `mappingForKey` and complete the mapping relationship as required. + +如果你只需要修改某个Model的Key的映射规则,可以重写 `mappingForKey` , 按照要求完成映射关系。 + +``` +struct Model: SmartCodable { + var name: String = "" + var age: Int = 0 + + static func mappingForKey() -> [SmartKeyTransformer]? { + [ + CodingKeys.age <--- "person_age" + CodingKeys.name <--- ["nickName", "realName"], + ] + } +} +``` + +### 3. designatedPath (指定解析路径) + +Override 'mappingForKey` to specify the parsing path + +重写`mappingForKey` 可以实现跨层解析。 + +``` +let dict = [ + "age": 10, + "sub": [ + "name": "Mccc" + ] +] +``` + +``` +struct Model: SmartCodable { + var age: Int = 0 + var name: String = "" + static func mappingForKey() -> [SmartKeyTransformer]? { + [ CodingKeys.name <--- "sub.name" ] + } +} +``` + +### + +## User-defined Value when decoding(自定义Value) + +SmartDecodingOption provides three decoding options: + +SmartDecodingOption提供了三种解码选项,分别为: + +``` +public enum SmartDecodingOption { + + /// 用于解码 “Date” 值的策略 + case dateStrategy(JSONDecoder.DateDecodingStrategy) + + /// 用于解码 “Data” 值的策略 + case dataStrategy(JSONDecoder.DataDecodingStrategy) + + /// 用于不符合json的浮点值(IEEE 754无穷大和NaN)的策略 + case floatStrategy(JSONDecoder.NonConformingFloatDecodingStrategy) +} +``` + +* Date + +``` +let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" +let option: JSONDecoder.SmartDecodingOption = .dateStrategy(.formatted(dateFormatter)) +guard let model = FeedOne.deserialize(from: json, options: [option]) else { return } +``` + +* Data + +``` +let option: JSONDecoder.SmartDecodingOption = .dataStrategy(.base64) +guard let model = FeedOne.deserialize(from: json, options: [option]) else { return } +gurad let data = model.address, let url = String(data: data, encoding: .utf8) { else } +``` + +* Float + +``` +let option: JSONDecoder.SmartDecodingOption = .floatStrategy(.convertFromString(positiveInfinity: "infinity", negativeInfinity: "-infinity", nan: "NaN")) +guard let model1 = FeedOne.deserialize(from: json, options: [option]) else { return } +``` + + + +If you want to control the scope of influence, you can override `mappingForValue` to give each attribute a different parsing policy. + +如果你想控制影响范围,可以重写 `mappingForValue`,给每个属性设置不同的解析策略。 + +``` +struct SmartModel: SmartCodable { + var date1: Date? + var date2: Date? + var url: URL? + var data: Data? + + static func mappingForValue() -> [SmartValueTransformer]? { + let format = DateFormatter() + format.dateFormat = "yyyy-MM-dd" + return [ + CodingKeys.url <--- SmartURLTransformer(prefix: "https://"), + CodingKeys.date2 <--- SmartDateTransformer(), + CodingKeys.date1 <--- SmartDateFormatTransformer(format), + CodingKeys.data <--- SmartDataTransformer() + ] + } +} +``` + + + +### Customize Transformer (自定义) + +If you need additional parsing rules, **Transformer** will implement them yourself. Follow **ValueTransformable** to implement the requirements of the protocol. + +如果你需要额外的解析规则,**Transformer** 交给你自己实现。请遵循 **ValueTransformable**,实现协议的相关要求。 + +``` +public protocol ValueTransformable { + associatedtype Object + associatedtype JSON + + /// transform from ’json‘ to ’object‘ + func transformFromJSON(_ value: Any?) -> Object? + + /// transform to ‘json’ from ‘object’ + func transformToJSON(_ value: Object?) -> JSON? +} +``` + + + +## Decoded finish + +### Parse the completed callback (解析完成的回调) + +When decoding is complete, **didFinishMapping** is called. You can rewrite it. + +当解码完成时,调用 **didFinishMapping**。你可以重写它。 + +``` +class Model: SmartDecodable { + + var name: String = "" + var age: Int = 0 + var desc: String = "" + required init() { } + + + func didFinishMapping() { + if name.isEmpty { + name = "-" + } + } +} +``` + + + +### Update Existing Model(更新现有模型) + +``` +var dest = Model(name: "xiaoming", hobby: "football") +let src = Model(name: "dahuang", hobby: "sleep") + +SmartUpdater.update(&dest, from: src, keyPath: \.name) +// after this dest will be: +// Model(name: "dahuang", hobby: Optional("football")) +// instead of +// Model(name: "xiaoming", hobby: Optional("football")) +``` + +If you need to change more than one at a time(如果你需要同时更改多个) + +``` +SmartUpdater.update(&dest, from: src, keyPaths: (\.name, \.hobby)) +``` + diff --git "a/Document/SmartCodable\346\211\247\350\241\214\351\200\273\350\276\221.md" "b/Document/SmartCodable\346\211\247\350\241\214\351\200\273\350\276\221.md" new file mode 100644 index 00000000..36818dcb --- /dev/null +++ "b/Document/SmartCodable\346\211\247\350\241\214\351\200\273\350\276\221.md" @@ -0,0 +1,110 @@ +# SmartCodable + + + +## 解析流程 + + + +### 非可选属性 + +#### 1. 缺少key + +try impl.unwrap(as: type) + +try type.init(from: self) + +func decode(_ type: T.Type, forKey key: K) throws -> T where T: Decodable + +let decoded: T = try forceDecode(forKey: key) + +使用初始化值 + +### 可选属性 + +try impl.unwrap(as: type) + +try type.init(from: self) + +func decodeIfPresent(_ type: T.Type, forKey key: K) throws -> T? where T: Decodable + +guard let value = try? getValue(forKey: key) else { return nil } + +#### 缺少key + + + + + +## 理解遵循Codable的类型的解析逻辑 + +包含Int,Bool等,都是一样的逻辑。 + +``` +extension SmartColor: Codable { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let hexString = try container.decode(String.self) + guard let color = ColorObject.hex(hexString) else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Cannot decode Color from provided hex string.") + } + self = .color(color) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + switch self { + case .color(let color): + try container.encode(color.hexString) + } + } +} +``` + +在进行属性解析时候,会先进入 + +``` +extension JSONDecoderImpl { + // MARK: Special case handling + + func unwrap(as type: T.Type) throws -> T { + if type == Date.self { + return try self.unwrapDate() as! T + } + if type == Data.self { + return try self.unwrapData() as! T + } + if type == URL.self { + return try self.unwrapURL() as! T + } + if type == Decimal.self { + return try self.unwrapDecimal() as! T + } + + // 如果解析的是SmartColor类型属性,此处没有处理,就会进入SmartColor的init(decoder:)方法中。 + if type == SmartColor.self { + return try self.unwrapSmartColor() as! T + } + + if type is _JSONStringDictionaryDecodableMarker.Type { + return try self.unwrapDictionary(as: type) + } + + cache.cacheInitialState(for: type) + let decoded = try type.init(from: self) + cache.clearLastState(for: type) + return decoded + } + +``` + +如果此处没有特殊处理 + +``` +if type == SmartColor.self { + return try self.unwrapSmartColor() as! T +} +``` + +就会执行`let decoded = try type.init(from: self)` . 系统会自动调度到`init(decoder)` 方法中。 diff --git a/Document/TestCaseSpecification.xmind b/Document/TestCaseSpecification.xmind new file mode 100644 index 0000000000000000000000000000000000000000..5335b43b0bb851f463549243d436e2fe8c97403f GIT binary patch literal 159664 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ĻH^Cqi}6U-*FU_d`t7wT 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

^I^Ti22g7+=i@~roGmAuKTTPmk~qV19o6& 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%0AYjAf6gy0g~ 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 literal 0 HcmV?d00001 diff --git a/Example/Podfile b/Example/Podfile index bfa900ac..8240185d 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -8,9 +8,7 @@ target 'SmartCodable_Example' do pod 'SnapKit' pod 'BTPrint' pod 'BTBubble' - - pod 'WCDB.swift' - + #对比组 pod 'HandyJSON', '5.0.0-beta.1' pod 'CleanJSON' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 7ee69809..868fe8de 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -8,14 +8,8 @@ PODS: - FBSnapshotTestCase/SwiftSupport (2.1.4): - FBSnapshotTestCase/Core - HandyJSON (5.0.0-beta.1) - - SmartCodable (3.4.6) + - SmartCodable (4.0.0) - SnapKit (5.6.0) - - SQLiteRepairKit (1.3.0): - - WCDBOptimizedSQLCipher (~> 1.3.0) - - WCDB.swift (1.1.0): - - SQLiteRepairKit (~> 1.3.0) - - WCDBOptimizedSQLCipher (~> 1.3.0) - - WCDBOptimizedSQLCipher (1.3.0) DEPENDENCIES: - BTBubble @@ -25,7 +19,6 @@ DEPENDENCIES: - HandyJSON (= 5.0.0-beta.1) - SmartCodable (from `../`) - SnapKit - - WCDB.swift SPEC REPOS: trunk: @@ -35,9 +28,6 @@ SPEC REPOS: - FBSnapshotTestCase - HandyJSON - SnapKit - - SQLiteRepairKit - - WCDB.swift - - WCDBOptimizedSQLCipher EXTERNAL SOURCES: SmartCodable: @@ -49,12 +39,9 @@ SPEC CHECKSUMS: CleanJSON: 910a36465ce4829e264a902ccf6d1455fdd9f980 FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a HandyJSON: 582477127ab3ab65bd2e471815f1a7b846856978 - SmartCodable: b11cd942bf4d7f00fbfd6adba1d37edc113f9e4a + SmartCodable: a93b23bfd09d29165fe1cb2b1e40ee2c759b2f2d SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25 - SQLiteRepairKit: a66145aadae91886c800f75e16f5cc6476af1a93 - WCDB.swift: 39e28fe29b5a3bf2927d9fb9218978f19bd49ff0 - WCDBOptimizedSQLCipher: fc5d49fe6761e54aad29e88da01b6fc1283e5759 -PODFILE CHECKSUM: c05dc28f2a31c55d860978b6a89fa7017b7f6ee1 +PODFILE CHECKSUM: 7f3af03f81934df0c035518074a7abbec8fa9d3f COCOAPODS: 1.15.2 diff --git a/Example/Pods/Local Podspecs/SmartCodable.podspec.json b/Example/Pods/Local Podspecs/SmartCodable.podspec.json index ce0e09b2..c280f413 100644 --- a/Example/Pods/Local Podspecs/SmartCodable.podspec.json +++ b/Example/Pods/Local Podspecs/SmartCodable.podspec.json @@ -1,6 +1,6 @@ { "name": "SmartCodable", - "version": "3.4.6", + "version": "4.0.0", "summary": "数据解析库", "homepage": "https://github.com/intsig171", "license": { @@ -12,11 +12,14 @@ }, "source": { "git": "https://github.com/intsig171/SmartCodable.git", - "tag": "3.4.6" + "tag": "4.0.0" }, "platforms": { "ios": "11.0", - "osx": "10.13" + "tvos": "12.0", + "osx": "10.13", + "watchos": "5.0", + "visionos": "1.0" }, "swift_versions": "5.0", "source_files": "SmartCodable/Classes/**/*", diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 7ee69809..868fe8de 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -8,14 +8,8 @@ PODS: - FBSnapshotTestCase/SwiftSupport (2.1.4): - FBSnapshotTestCase/Core - HandyJSON (5.0.0-beta.1) - - SmartCodable (3.4.6) + - SmartCodable (4.0.0) - SnapKit (5.6.0) - - SQLiteRepairKit (1.3.0): - - WCDBOptimizedSQLCipher (~> 1.3.0) - - WCDB.swift (1.1.0): - - SQLiteRepairKit (~> 1.3.0) - - WCDBOptimizedSQLCipher (~> 1.3.0) - - WCDBOptimizedSQLCipher (1.3.0) DEPENDENCIES: - BTBubble @@ -25,7 +19,6 @@ DEPENDENCIES: - HandyJSON (= 5.0.0-beta.1) - SmartCodable (from `../`) - SnapKit - - WCDB.swift SPEC REPOS: trunk: @@ -35,9 +28,6 @@ SPEC REPOS: - FBSnapshotTestCase - HandyJSON - SnapKit - - SQLiteRepairKit - - WCDB.swift - - WCDBOptimizedSQLCipher EXTERNAL SOURCES: SmartCodable: @@ -49,12 +39,9 @@ SPEC CHECKSUMS: CleanJSON: 910a36465ce4829e264a902ccf6d1455fdd9f980 FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a HandyJSON: 582477127ab3ab65bd2e471815f1a7b846856978 - SmartCodable: b11cd942bf4d7f00fbfd6adba1d37edc113f9e4a + SmartCodable: a93b23bfd09d29165fe1cb2b1e40ee2c759b2f2d SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25 - SQLiteRepairKit: a66145aadae91886c800f75e16f5cc6476af1a93 - WCDB.swift: 39e28fe29b5a3bf2927d9fb9218978f19bd49ff0 - WCDBOptimizedSQLCipher: fc5d49fe6761e54aad29e88da01b6fc1283e5759 -PODFILE CHECKSUM: c05dc28f2a31c55d860978b6a89fa7017b7f6ee1 +PODFILE CHECKSUM: 7f3af03f81934df0c035518074a7abbec8fa9d3f COCOAPODS: 1.15.2 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index f9bed8bd..16efb55b 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,1069 +7,498 @@ objects = { /* Begin PBXBuildFile section */ - 0081DCBC76F13C6AC51BC74BAA8B2A49 /* CleanJSONKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5FEADCF099B87D561589E2F744AE16 /* CleanJSONKey.swift */; }; - 00A2749F46C967ED4725A32357E3FB1B /* ConstraintLayoutSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B780DB2E145B03662828DEC1C5D1132F /* ConstraintLayoutSupport.swift */; }; - 018CC6BBD089090F514FF8AFF8606672 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 01D7C42C2EBCDEE08A99DAA7F9ABDE4A /* TableBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB84981C58672F8E06A0D4AC94C3282 /* TableBinding.swift */; }; - 02485FF1AE2CAB3D8A57BE62888AF328 /* printf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E993CD880CBB3208C2A588FB128358 /* printf.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 02560F1312F13EF15E0EB5FA952C9A48 /* PointerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7758FB3B629E7C38E290756F49F3101 /* PointerType.swift */; }; - 02D671D5D10D160AAB069825595FD4CE /* SmartKeyDecodingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7336366091CEA7AA3B99B1550BB520 /* SmartKeyDecodingStrategy.swift */; }; - 03B49B92AB291DFD32642233E5EDB638 /* os_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = D02525015C11C983A716B56C77A390BA /* os_unix.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 04094574EAFF035388C27E465B917745 /* SmartCaseDefaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56F0CCA54FAF427CF38B01CBAAE7E03D /* SmartCaseDefaultable.swift */; }; - 044973538553B114516678D144E318CA /* Serializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 007BA55F5D4490BD94C8451E76A00455 /* Serializer.swift */; }; - 04637C70546B34F93C3A1D79C3F78B37 /* ConstraintDirectionalInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E57B503B4EBCFD7AA0E51360A97AE18 /* ConstraintDirectionalInsetTarget.swift */; }; - 046632AA5E3B8F69BCE2BB01F7B84015 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 047D3D772E8DDA418069EFA573B36BD2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 0591132B5EA1BE4DDA268D8A9C3D0421 /* LayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81E6BEF09C7E97AF72776F1CA7F474A /* LayoutConstraint.swift */; }; - 06E43B4751069B47B3BD4AFD936A57E3 /* ConstraintPriority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60AD687D99290D39682062FBAB4B9530 /* ConstraintPriority.swift */; }; - 06F077368CE7C4C411228D0BFBC3522E /* sqlite3userauth.h in Headers */ = {isa = PBXBuildFile; fileRef = C14D61C7AE59E97D0F73C27659D8489D /* sqlite3userauth.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0833E66E7F19849322305D67777B77DB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 0863D5CFCA5BA780AA8C685687F4A034 /* JoinClause.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1710B685152D86B0CBB66C7CFD397597 /* JoinClause.swift */; }; - 09248AD7A82D172C0DF90D9B9A5A6043 /* StatementPragma.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3E80998BCA7EF85CC765918FD0D670 /* StatementPragma.swift */; }; - 09770D71BC9E55593D155BB29B2F1FC7 /* build.c in Sources */ = {isa = PBXBuildFile; fileRef = 46611858B8325FB36AD0D5F498366D03 /* build.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 0A188E966049728E55F6E95C317CC3F5 /* sqliterk_pager.c in Sources */ = {isa = PBXBuildFile; fileRef = 5100DD0D061A6FC95142F30916FF35E1 /* sqliterk_pager.c */; }; - 0B5FA55BBADB420979502AA43824502E /* StatementRollback.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20F883B8D4C68B3B3B7937CF3DA069D /* StatementRollback.swift */; }; - 0B994CDC79B1AD3A7BE62490D27C60C8 /* ConstraintAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9FD46ECA8E8E5EF9E6B7EB1AF5495D /* ConstraintAttributes.swift */; }; - 0D854DADBA09FA6C54F1511216223D74 /* Redirectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D02FC03949EB55EFDEB6BD91B376C88 /* Redirectable.swift */; }; - 0E6C5F92B5085DE1351848F5A4BD6EDE /* Operable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED8325151406ED11C82AF15BBFD7E6E /* Operable.swift */; }; - 0F4D0B7B522466B970AA826F57343EFF /* DataTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54DA92E53C8E33D0D0C63CDF41C84CF /* DataTransform.swift */; }; - 1074C42B5CE541D3BB1CED0E33797CBC /* SQLite-Bridging.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B7110CEA112EBF2FC498D5380951730 /* SQLite-Bridging.c */; }; - 114AD2ADB1B9F746B7A1DF0CB8F93598 /* resolve.c in Sources */ = {isa = PBXBuildFile; fileRef = 2083F64F2D96303B570E6175B352347C /* resolve.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 116592853664BF5C14932F7FACFBD65F /* btree.h in Headers */ = {isa = PBXBuildFile; fileRef = AF7E6F369E3B04273EEA3F174700C2E0 /* btree.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 121A1E851C4ED624C40C631C653B12A6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 123E6BAD784E74477DC5B5CFF0272759 /* AnyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC9E37E1231F7C47C1FF217714CB44C /* AnyExtensions.swift */; }; - 1301D909C810F9EC07D5360EC8FB1E8B /* Convertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194C0EE64ACC9E3E4B7814090F7A7E53 /* Convertible.swift */; }; - 135DA831CB3A165481A621F982F5AD25 /* sqliterk_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = A2BA444A4E60E7EA50A97DCF8F4CC456 /* sqliterk_crypto.c */; }; - 138687962513B5FC55762512233493F5 /* sqliterk_api.c in Sources */ = {isa = PBXBuildFile; fileRef = EB44A0EAF3083A0C1BB831A625B3A464 /* sqliterk_api.c */; }; - 14714B4F87060C2206F43EFD8EAE7E23 /* fts3_snippet.c in Sources */ = {isa = PBXBuildFile; fileRef = 446B401C0DD4B21F9A9BF00840223ED9 /* fts3_snippet.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 14848FEE4EBDB5AC5ACD05E5E9A12280 /* vdbe.c in Sources */ = {isa = PBXBuildFile; fileRef = 5283B716A76A18C9B408E0035F555B6B /* vdbe.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 149AA8EC391DDB12B60FAC4501F83FD5 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9930E634CA9F9592BA112E4EA073572B /* Error.swift */; }; - 16B4411868155DC93F0DA1DEC1AAD005 /* status.c in Sources */ = {isa = PBXBuildFile; fileRef = 35E2F9F18CD38FADE9FBDBA79C2036A5 /* status.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 171087EAEF2F515323D793C279D98109 /* Tracer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88B551F69097A3D9A651BB19E4806AE /* Tracer.swift */; }; - 17B9A1C9CB9555CF5C3D70318BD98BFF /* BTBubble+Check.swift in Sources */ = {isa = PBXBuildFile; fileRef = B507A62DC4EBD3BB69182CD41E19AEDD /* BTBubble+Check.swift */; }; - 183D8B3E057B885EA7DF9A8CDCCE9029 /* ConstraintMakerRelatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9E48CF5B436F03A644A3F2079E06A5 /* ConstraintMakerRelatable.swift */; }; - 19BB09AF94BD545E40C2766045BDDD77 /* ExtendCustomBasicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57D9A0F7AD288FBCB187DF9CCC042E97 /* ExtendCustomBasicType.swift */; }; + 0081DCBC76F13C6AC51BC74BAA8B2A49 /* CleanJSONKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 555C1F46B8C3D9749B4FADF32ED4458D /* CleanJSONKey.swift */; }; + 00A2749F46C967ED4725A32357E3FB1B /* ConstraintLayoutSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544353E196F6C41D2674EF54DDCED631 /* ConstraintLayoutSupport.swift */; }; + 02560F1312F13EF15E0EB5FA952C9A48 /* PointerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5AD1AE1022A579A49D4DE848C3C5D9 /* PointerType.swift */; }; + 044973538553B114516678D144E318CA /* Serializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FD01EC1237ED966BE6C99E868971093 /* Serializer.swift */; }; + 04637C70546B34F93C3A1D79C3F78B37 /* ConstraintDirectionalInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = C53C2DBE2FECF12DA6C33264A027EC82 /* ConstraintDirectionalInsetTarget.swift */; }; + 046632AA5E3B8F69BCE2BB01F7B84015 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 047D3D772E8DDA418069EFA573B36BD2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 0591132B5EA1BE4DDA268D8A9C3D0421 /* LayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D532B60E5A862BAED6B9ED6A3A06F7 /* LayoutConstraint.swift */; }; + 06E43B4751069B47B3BD4AFD936A57E3 /* ConstraintPriority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1648D17E6B6A33B54A7906BC560E10 /* ConstraintPriority.swift */; }; + 0833E66E7F19849322305D67777B77DB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 0B994CDC79B1AD3A7BE62490D27C60C8 /* ConstraintAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DD3A510DCBD287B46973C5625A7FB1 /* ConstraintAttributes.swift */; }; + 0B9BA74A4B04EF2A0957499A7F3ABA6B /* JSONFuture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61B5EAF366B8557B8062A765F73500C2 /* JSONFuture.swift */; }; + 0F4D0B7B522466B970AA826F57343EFF /* DataTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB121D8A9523A91FDAB8376BE09FD /* DataTransform.swift */; }; + 121A1E851C4ED624C40C631C653B12A6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 123E6BAD784E74477DC5B5CFF0272759 /* AnyExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD07779AA8B42688ED0FF74BACC5AA5 /* AnyExtensions.swift */; }; + 13AF0E06C5C19F0B6FC9EBB5A56B38D8 /* URLTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5490ABF50B6719BC634405F60AB3E6 /* URLTransformer.swift */; }; + 17B9A1C9CB9555CF5C3D70318BD98BFF /* BTBubble+Check.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319CD0A8663A00A572B4418C10FE8894 /* BTBubble+Check.swift */; }; + 183D8B3E057B885EA7DF9A8CDCCE9029 /* ConstraintMakerRelatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD311A04C42FFDF8D95E30DC09B7EA57 /* ConstraintMakerRelatable.swift */; }; + 19BB09AF94BD545E40C2766045BDDD77 /* ExtendCustomBasicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63337F29437FD6A05DCA6E50C4DF6945 /* ExtendCustomBasicType.swift */; }; 1A78E1104DB6D444ECAF63AB362C8115 /* Pods-SmartCodable_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E3F09186EE217FC9713BA39404EB7B24 /* Pods-SmartCodable_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1B14ABB3EBE1CF1E69D4E393ADE3E9E4 /* OtherExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40DE48CED81F4007A52E53CD61D79161 /* OtherExtension.swift */; }; - 1B8CE6509886B2FF237F5844B9C64C8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 1BACCB396E184BBE1534DA7B2537578F /* CleanJSONDecodingStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C357740AEE6772021A24F0E4114A600F /* CleanJSONDecodingStorage.swift */; }; - 1CF436D2F5EA067217400A58CE3256CC /* Pragma.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14E440614E76DBC6A5930D8F20B2042D /* Pragma.swift */; }; - 1DF22A9F17E1CFAF5E59338E22FC4ECD /* pager.h in Headers */ = {isa = PBXBuildFile; fileRef = 81A6B148540C158469908690D628A9BF /* pager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1ED0F18831A8F84E9F989991DF54AD5D /* mutex.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B5134C3B0D0DCBF20DA94AC4C405B7 /* mutex.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1F097EC7770FD4A1A9A8FD4770037684 /* pragma.c in Sources */ = {isa = PBXBuildFile; fileRef = 0E157DD40B43D7133F4386E4833E41D3 /* pragma.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 1F1AC390BB78B11FD3F67C5BB9B754C4 /* crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = 9D5E5FF169696273D350DDAD938BA59C /* crypto.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 1F84FE646CD1D7BAFFB58C243277AFF8 /* FBSnapshotTestCase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 314EE032EFE20CD4E06F74092A6C187D /* FBSnapshotTestCase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1FBE8E245651194A2F6F63E1AECD92E4 /* notify.c in Sources */ = {isa = PBXBuildFile; fileRef = 959A3546F4262DC0138394886AA3D28D /* notify.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2029AF0F75B276BC4CF326EAC1D03BAA /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = 468DF5A09D8D79ADC328CC7F75D956AF /* Property.swift */; }; - 20B4141230DED5149833C6554AFC8EFB /* _CleanJSONDecoder+SingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F201352441D0808E12B12C1B02950B /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */; }; - 21B71CBFE18C8A24D9198B694A6BE31E /* sqliterk_pager.h in Headers */ = {isa = PBXBuildFile; fileRef = EFE265BEFD53265D1B57FD37F6C1C080 /* sqliterk_pager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 21D9A9BF7A6DE6222221999E6400385A /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 18D88FE24C75AD053966BC639186BD5D /* hash.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2208D53630DF0F336A8D9934D53EA740 /* LogItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9285283C0400C69E185F4F4E5C3699A /* LogItem.swift */; }; - 220D6AC9B1B1EC8EFFB204F9C1EAC842 /* ConstraintMakerEditable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BC254FD8EC10D39D0B946E545B0AC6D /* ConstraintMakerEditable.swift */; }; + 1B14ABB3EBE1CF1E69D4E393ADE3E9E4 /* OtherExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D0C8FFA3D3F1791A00D06DA9FB06C3 /* OtherExtension.swift */; }; + 1B8CE6509886B2FF237F5844B9C64C8B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 1BACCB396E184BBE1534DA7B2537578F /* CleanJSONDecodingStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34C278263A81DD03B77202C061698C /* CleanJSONDecodingStorage.swift */; }; + 1F84FE646CD1D7BAFFB58C243277AFF8 /* FBSnapshotTestCase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7FF03B8E2DF800F666228FD3C0F9026B /* FBSnapshotTestCase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 20B4141230DED5149833C6554AFC8EFB /* _CleanJSONDecoder+SingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD6DAD58F97DC6978669ECC1DCB217 /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */; }; + 20DBC391BAF1612B228ACF871D5B43D7 /* SmartLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9DA5A2D5BD3067E4B62F006F3BCE6B /* SmartLog.swift */; }; + 220D6AC9B1B1EC8EFFB204F9C1EAC842 /* ConstraintMakerEditable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3CBC4CFD3D5E9ABDC56DDC685EACE4 /* ConstraintMakerEditable.swift */; }; 2307EFF154B93A7CF3BBD066F9D2479E /* Pods-SmartCodable_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E5FA84A6FC991F1497F1DC0F7EA5CAD8 /* Pods-SmartCodable_Tests-dummy.m */; }; - 245DA35A0C392F8A369661C0B1B73653 /* LiteralValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F56261BCBCA2343ACB3164AE2B218462 /* LiteralValue.swift */; }; - 24658CFD39BCB4586D56C427F8EA751D /* BuiltInBasicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C85D39B63CA259934A33F2B43CA2305E /* BuiltInBasicType.swift */; }; - 251624DA7D7904D33EB98FC6EAE62CAD /* SmartSONUnkeyedDecodingContainer+decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEDA3C22B4FE876F9B1AE3E0300A4C9 /* SmartSONUnkeyedDecodingContainer+decode.swift */; }; - 2556E6D6E136822FDD7583D50D460C3A /* fts3_unicode2.c in Sources */ = {isa = PBXBuildFile; fileRef = 2ACC1B7946BEDD0237B5D92F1A9EF9F3 /* fts3_unicode2.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 256558233B40ACA6818F143BBC5B8017 /* ConstraintViewDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B27DA73869030B61A7DD375B3D22632A /* ConstraintViewDSL.swift */; }; - 2646AF70FF516BE8741AF8AB0BB10217 /* dbstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 30204FFE690A0B9592706A78093E1503 /* dbstat.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 268E861FB1940887EE37338C0D99CFBF /* fts3_unicode.c in Sources */ = {isa = PBXBuildFile; fileRef = 153C1F6555FA7C044BD0F0CC4C375069 /* fts3_unicode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 269A21F134292C4A451050823CB92255 /* sqlite3ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A19D339940591628408D7B9957A84CF /* sqlite3ext.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 277BD70D62A60D10488C2588712D46C7 /* fts3_tokenize_vtab.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BE8BC5AD3696828942B96191FFC93B /* fts3_tokenize_vtab.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2878735FE61E1EEB4C493A8B8ED3DCAC /* EnumType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15335B1C99316156D53EFB132C72D90B /* EnumType.swift */; }; - 29224605D129F61D1532BCE2A8614F4E /* CodableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A67D02E48C372F7F65EF8E90E5E4446 /* CodableType.swift */; }; - 2975A09730FD83DC0897129A11EA6585 /* SwiftSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6413BD32DD33B3C006539834A6029F46 /* SwiftSupport.swift */; }; - 2A25F3EB16B983C2BBE9A0EC0FD9B131 /* RWLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F8D67CFB1FB3199FB53CCFDA73794D /* RWLock.swift */; }; - 2B8005A25AB53F75BF876C529F2E8A4F /* btreeInt.h in Headers */ = {isa = PBXBuildFile; fileRef = F77B4DD50B4E2BA5873C6AB52E4A8664 /* btreeInt.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2B88C28DD20CBFA7B3AEB21A365197FE /* FBSnapshotTestController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8944B5E835D69F7ACF99BAE48649B2BF /* FBSnapshotTestController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2C0C1992B978CADF14B0E06B8499C89E /* fts3_expr.c in Sources */ = {isa = PBXBuildFile; fileRef = C63C50EBF0AE1A7E3E83D4462CD73A8D /* fts3_expr.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2C701B2907762546B2D793023C3214D7 /* SmartJSONDecodingStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1187CAE253A8264680CBBC4D3BF3AE54 /* SmartJSONDecodingStorage.swift */; }; - 2CB61F6FA511CAACB43A50DC3A82E0DD /* UIImage+Snapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = BFA871D4B31BEA3D4DF3421A0453A0B6 /* UIImage+Snapshot.m */; }; - 2D3800F3747D531C8793755D6137DF64 /* btmutex.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3A6680786E7AEEAEBF6ACBC7F46634 /* btmutex.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2ECCAC52EF4C74E1032E0BC646BBE5B9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 2EF27A7A5ECA0D884396986AA39FA134 /* crypto_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 248FD8535E726D670FA271336DD6BD81 /* crypto_impl.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2F53741EC84A0BE1806E28F79E3F331D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 2F85152F2FA3BBDB54B8C8AC78C3FB1C /* mutex_noop.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E60F4510824A7A8EADD930362F84E30 /* mutex_noop.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 302638AD965D971A268A2114F7742607 /* CleanJSONUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 837D4D1D0F21909CC79D931A54D8C932 /* CleanJSONUnkeyedDecodingContainer.swift */; }; - 30544F2A4D2D9EC72607B8BDB220FA77 /* vdbemem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27C5818B69BFD80E9CD7AB0525DF22C2 /* vdbemem.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 309C54EC9536180B960B9CB8EBD412E3 /* CustomDateFormatTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF792627DE1714E38E8A9B2C7DA6A6B2 /* CustomDateFormatTransform.swift */; }; - 30D475DF57C0C682A723231E7BCA0D14 /* FBSnapshotTestCasePlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8462A4E4A62FFAA2EA934440DD042D /* FBSnapshotTestCasePlatform.m */; }; - 31BBDE6D8EF669C30F5140D8058DCC76 /* CleanDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABF6303B4915731785B890B96086080 /* CleanDecoder.swift */; }; - 33BC540DE351661FAAA24950E165D4F1 /* MangledName.swift in Sources */ = {isa = PBXBuildFile; fileRef = C177859E1A60F619FF28EED9334F6BFC /* MangledName.swift */; }; - 361EA7ABBDD80F154DDC208D9CE920DD /* Deserializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9E2E9B8EEBD6E444845703ABB17FA8 /* Deserializer.swift */; }; - 3660B4F629053ABC3C1DF69366770289 /* ConstraintConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D8B544917AB1825600223F1847F8ED /* ConstraintConfig.swift */; }; - 36E9CA298A5928DF3351A92DA4A59C32 /* sqliterk.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B9BEE2C0EC151B67961F46092A989DE /* sqliterk.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 373413256658309F9053CE22BF62077E /* UIImage+Snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = F6AEFAF46A1EB958A79BAB5E3AE57152 /* UIImage+Snapshot.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 380F4FCB4A16A8BEE8C65EDDA025FEF3 /* _CleanJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929712FD14C65CBAF44B3BA838DCFB36 /* _CleanJSONDecoder.swift */; }; - 387D6EF5FCADD267664EFD984CB6265A /* backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 2FACBD8B689AF9C3F28B0EE67CE6F169 /* backup.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 38B9D58E94D9C1CECD7E381C64A2329D /* UILayoutSupport+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C620067F708F6A1819086FB1A562860 /* UILayoutSupport+Extensions.swift */; }; - 38D8B03AFC5B21317B7F8C0F21321E9D /* wal.h in Headers */ = {isa = PBXBuildFile; fileRef = D54143E7A4BC63635B0089DB6810A04A /* wal.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3A030CA5A4DD41F59802F907A93F85DF /* HexColorTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345CF363ECE5628BDA0E1001B5661B0F /* HexColorTransform.swift */; }; - 3A303FCED61BCB29B3FD26735BB9889F /* sqliterk_os.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DCAC454A3B4DC896C97A76C0162F55F /* sqliterk_os.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3A931F2D706945121204F41FFB56DABD /* SmartCodable-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B1200BCAF314037FF573D41166091D8 /* SmartCodable-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3AB098E905CC590F7D3FD840511EA3E3 /* rtree.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D0D80684CB2A17DDA87A11515761E6D /* rtree.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3C53583CB1A5F4926491D8838F580074 /* BuiltInBridgeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FFCB8A3A3DABA88D9B4E1ADB6B2BC15 /* BuiltInBridgeType.swift */; }; - 3C79B19BA1FD57F5C3341E070695C021 /* delete.c in Sources */ = {isa = PBXBuildFile; fileRef = 81DB024EC9AFF73AA4502F4734CA810C /* delete.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 3C90C08CA74CC0906DBDD0B4B6AFF100 /* mutex_wcdb.c in Sources */ = {isa = PBXBuildFile; fileRef = D902F67F84D016160BC9C30B93A8F564 /* mutex_wcdb.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 3CB868B683BDE4E813CAD9C86B56B033 /* _SmartJSONDecoder+SingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53D77D9C85C14C7889D991953799A90D /* _SmartJSONDecoder+SingleValueDecodingContainer.swift */; }; - 3D8C435D4C19F8220CFC4E18E8E1CA9A /* mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = 5750120103B02747856DF9A69B4BCC83 /* mutex.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 3DDBBEAD85435705CDCF8E55243846CF /* os_wcdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 6A335F1EDB942166F2779121CE29E585 /* os_wcdb.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 3E1D9E1EBB1AC16C6639C9CEF65DB151 /* Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F45E6394093E1369C044D428C8879A /* Order.swift */; }; - 3E6B2551A92F752B92AE04D85AD2360F /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69EED8E214F52686EF00631CE13D11DA /* File.swift */; }; - 3E78F4F6E99E13A7CB10FAF2A5292797 /* sqliteicu.h in Headers */ = {isa = PBXBuildFile; fileRef = 944178E3D8552FB8678D163FCDF781F4 /* sqliteicu.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3EBEC269AF9440CB77BA0140E3C565F5 /* callback.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F8BF617506C58E3EDF6131E3780534E /* callback.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 409FF499AEF8324ABFBA13C7A68D6349 /* BTBubble-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AC26795DE4514FE32D3094E1B9384FC6 /* BTBubble-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4204A64235FD88B9A1F69D071E5E395F /* Conflict.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4935A7C5516AB70886A15F59CC104A /* Conflict.swift */; }; - 42B6ACFCF650183030867CB3EF345E95 /* ConstraintMakerFinalizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A63818CFAB3CDEB4D9CE9D9BABC4541 /* ConstraintMakerFinalizable.swift */; }; - 42C3DF2D76E9E3E9AA70B53407AF0072 /* sqlite3rbu.h in Headers */ = {isa = PBXBuildFile; fileRef = 82C013A66AAE87D26F22C959065F6D3B /* sqlite3rbu.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 42D3A5AFF2E7B24252CD399BBDC5E654 /* DataTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE209EF17490B7AE639036689E60ACF /* DataTransformer.swift */; }; - 431AAFBB20F0A2F30909DE889C34FE7F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3208D7D718A79BBC3B9384E32256F6A /* Security.framework */; }; - 43AEF76844A559D0319F273F5E688613 /* auth.c in Sources */ = {isa = PBXBuildFile; fileRef = 3DA5B0BB29BEE655E198C29614913C2A /* auth.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 43B53856DBC504EF1A94D6A14A74E752 /* SteadyClock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F209D4AE80852F7B2A473B433E6231 /* SteadyClock.swift */; }; - 43F4C76847364198EF7A43C247219858 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = E07019FEB983E7289826370A121CFF96 /* Optional.swift */; }; - 443F8883D7EB29311780684738AE71A0 /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = B6FD93E2638B8D26614D584022725EA7 /* hash.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 445236A640179D6E181C4C6E4A0829BE /* Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 338B1D796753AF41826F3EC41206089D /* Convenience.swift */; }; - 45B320FB7573471F838C781BC975C2AA /* queue.h in Headers */ = {isa = PBXBuildFile; fileRef = 20BCCD509CA9B3F4E19F0B89D1F0DA9E /* queue.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 45ED255F3838C9661EAFA906F8BA79DB /* fts3.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B13703C34892E109DC262AD9E026413 /* fts3.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 45F29B90443A2B5B18BCC90E6C49AA15 /* window.c in Sources */ = {isa = PBXBuildFile; fileRef = 27E0C82161F76C3621B9957E27ECF4E4 /* window.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 46BD19D7708E8AAA015506480ED796A5 /* BTPrint-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CA7F1846B98306446ECE67F2856D9BB /* BTPrint-dummy.m */; }; - 46BDDFC8D55447DF41D3EB14E31DA934 /* upsert.c in Sources */ = {isa = PBXBuildFile; fileRef = 06748A1A350AAD18055FC22AD20BBB46 /* upsert.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 46F8DF51B898A743A704F10A78390817 /* fts3_tokenizer1.c in Sources */ = {isa = PBXBuildFile; fileRef = FDC31AE155953A80BB668497C4AC2BA0 /* fts3_tokenizer1.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 471E3E2EEDB58C3AD3551EB00BB6C2D9 /* date.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A21FD23B7B9D638D2D6437D1FCEEB48 /* date.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 475FF86E21EF441D2A5EF28F6B254A5F /* icu.c in Sources */ = {isa = PBXBuildFile; fileRef = D576389A8088EF7132E5C2014B4EE239 /* icu.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 48AD197B8AAB83CF9F6CF02BA286DCA9 /* fts3_aux.c in Sources */ = {isa = PBXBuildFile; fileRef = E5C698A33CA71DF66125CB48E115C9D1 /* fts3_aux.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 49848A2E0517D0DBE730337A2487243D /* vdbeblob.c in Sources */ = {isa = PBXBuildFile; fileRef = 4886E29175151E6108F75868065ABBF4 /* vdbeblob.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 4B15E1711B97D1607B6D3AB5288A7468 /* trigger.c in Sources */ = {isa = PBXBuildFile; fileRef = 0D452F86E76CB24DF6ECA35D83AA8248 /* trigger.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 4BAD99B7394E225CEDBF94B8100BCC7F /* ConstraintRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1ABE47C1F1223A420137396A81E391B /* ConstraintRelation.swift */; }; - 4C43602DEBAEEBCD4C2C923BDD23533D /* Describable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8F51139F0FA15FEDE192F7F29A3781 /* Describable.swift */; }; - 4D9E3A4C588EA10E1B072DD95DF150E9 /* CleanJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 298E9370B4A805049548CB01C7F08CF6 /* CleanJSON-dummy.m */; }; - 4DA72FD7F1FB2C0449EDEF4B8A579807 /* ConstraintPriorityTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 327DC9387C1368E032434452F72153B7 /* ConstraintPriorityTarget.swift */; }; - 4DF8F8D5DBF3DC1119AB593C46D045B1 /* fts3_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 940A8C6613C7BC0BF47F245097A1BCAC /* fts3_write.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 4F529B52D98B333CCF6967D3CAF87AC8 /* StatementCreateVirtualTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CA8D934CA4195CBB60E7B64B4F6938D /* StatementCreateVirtualTable.swift */; }; - 500C3D73A19D8FD96D70B00D4B23CB60 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = A343A2044144CB7474985FA357554BD0 /* fts3_tokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 51462C8D3990BE833959AE1F32EF4C41 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15AA5C0185FEA92FCCC59356558DB25B /* Core.swift */; }; - 532888C4FAC628464F216E4FFA56D58C /* DecodingProcessCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E78CA67C1117E52EF3FC13EB351A6819 /* DecodingProcessCoordinator.swift */; }; - 5380454C48A12A6E376122ABD8096968 /* ConstraintDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B544865E9FB982351862D454EB97A62 /* ConstraintDescription.swift */; }; - 542FCBDA339A22D556E13002BFD717EF /* StatementAlterTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE3C52BE9E38A8757F78EF0A1829CE /* StatementAlterTable.swift */; }; - 545F820CC9C430626698E3D80323EBB8 /* btree.c in Sources */ = {isa = PBXBuildFile; fileRef = 981FC3D828F7DDCD2F77A0BF2CEB5313 /* btree.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 546CE5582F822B2C395D382A46594897 /* SQLite-Bridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A8D1A79FED4B435F107DC9231BCFBF3 /* SQLite-Bridging.swift */; }; - 5479481080E8B03DAB47E61F67AC3F64 /* vdbeapi.c in Sources */ = {isa = PBXBuildFile; fileRef = E690F4F3A52E7BD1C7B5AEF2B5DA6211 /* vdbeapi.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 552485DFCAE48E5A29DEFD104DBD7554 /* VirtualTableBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCB1D63CBD4130578F32B453D318E7B /* VirtualTableBinding.swift */; }; - 5558B876B579BC1E79BD3D2B19148329 /* UIApplication+StrictKeyWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CF972F529FCD52A4837EF7384E25630 /* UIApplication+StrictKeyWindow.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 55B83E4D45CE7387DE155AFD083F7455 /* StatementDetach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4FA0CCF2A2DA9C40F7751A1FA54192 /* StatementDetach.swift */; }; - 55E51F45F1E157D3B4942BA7252C277E /* ConstraintRelatableTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4841EAB23923FDF7466BD02E50A85A28 /* ConstraintRelatableTarget.swift */; }; - 56A72F6D13D930C4A2568F24DEA33C8D /* ConstraintLayoutSupportDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D22BA786978818F4FE3FDB91C56F4A1 /* ConstraintLayoutSupportDSL.swift */; }; - 56AC6DC6459AE47E7BC4AF06E5B148D2 /* ConstraintDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14972CEEF09B3920E3ED07D20713219B /* ConstraintDSL.swift */; }; - 56CAC06DB79E51F4ED416927D57C79A9 /* Measuable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30725197DB5D704DA8C15608B3F3AC42 /* Measuable.swift */; }; - 56DA284ABCBA338B207BC5CDDEA1D687 /* vdbe.h in Headers */ = {isa = PBXBuildFile; fileRef = 16FAB580F3341857A02C000870F30103 /* vdbe.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5738F827DE4798236556220F211BC23B /* pcache.c in Sources */ = {isa = PBXBuildFile; fileRef = 0138F7570768B19CEE6F7AB7AE7D1841 /* pcache.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 580FE14211553843A3CDF2B13DC97E6C /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D0587A335645BB79F0222497FF85E14 /* SQLite-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 599A4EA710D33BB9D940F534BFD58EE6 /* TableInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F652B64AD7EA719869A9BB4E4D5B39A /* TableInterface.swift */; }; - 59C0CE0F609F6A0C6E5A2A66CCE9B154 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F3BEEE19C0A78E1A2CA95A33072BA36 /* Atomic.swift */; }; - 5A8FAA2FBC1E5BC5F5137CB211218A1E /* CleanJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81B9DCB1C5F346CFD0DDFE4DBB79691 /* CleanJSONDecoder.swift */; }; - 5BAF79C63655A4F5CE51D5766A12BA4B /* sqliteInt.h in Headers */ = {isa = PBXBuildFile; fileRef = B85B1B1333F12E9C10C98F336EB35B05 /* sqliteInt.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5BE525FF6FA14B999ED2CCC0AA4FA0CF /* FBSnapshotTestCase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C12BFAA6F02D6D9B0F42E75644DD5E /* FBSnapshotTestCase-dummy.m */; }; - 5CCB87A1A86D7C03A5D678B262B37071 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - 5D0C8EE39661E929D4881B314AA90123 /* ToJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = B68373D3DB223AC11F1B7D84FCDBFC8A /* ToJSON.swift */; }; - 5D36B99F3CAB1FC7337082D9581FECA6 /* Debugging.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADDAA04F64E571FD4FDEB5F3133A447A /* Debugging.swift */; }; - 5DC73AA815A59F40B06AAAEF2DEAB163 /* update.c in Sources */ = {isa = PBXBuildFile; fileRef = 79255177DD8C05F8B7066A72ADC29525 /* update.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 5DCE38107310E0DD000C18BD3307E496 /* sqliterk_values.c in Sources */ = {isa = PBXBuildFile; fileRef = 26F087E6B19DA0211F8B01B1D81F844C /* sqliterk_values.c */; }; - 5ED6076425D3E139315811A196607219 /* StatementTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF047CA737FB19838BEC0244141C05B /* StatementTransaction.swift */; }; - 5FCE0936FD3B817C74C1EB6B26D459D7 /* BTBubble+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5DFE21D0BEE989AE9E8287E5BEE62A5 /* BTBubble+Menu.swift */; }; - 5FD7858E6AA15774EDCD172DFE731D66 /* JSONAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CFEEBCF51169AF0B1F315D69C8D33F /* JSONAdapter.swift */; }; - 604D3C93C17978C23600EC415949AB64 /* ConstraintInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16AD943F9AA80E1E0F94A0D7B760B5BA /* ConstraintInsets.swift */; }; - 611CEF7FF1EF9EA1BCEF6C73EEE3ACCF /* ConstraintLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F8F94803B65B561FBB046FCFCE4EA7 /* ConstraintLayoutGuide.swift */; }; - 61FCA0616CE6512DCA67D74562D6EA1D /* ReflectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C3547D57598A7565784581664A1EB4 /* ReflectionHelper.swift */; }; - 624FA95B57D16D9F791F2B1B0DC7BA84 /* HandlePool.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2AB63F2AC5AC4FBB2A1B85A3A1BB92 /* HandlePool.swift */; }; - 62C1A489E5C6414819815F3219B52FE8 /* URLTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1662A646B256DAAC436E92852D15012 /* URLTransform.swift */; }; - 62F836923F08713C061A1AE9CDC74151 /* ModelKeyMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59FD30BFD517239EAEF40A0E82542733 /* ModelKeyMapper.swift */; }; - 63B9717578FE35D0E8031F5376631E70 /* ColumnType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8053B0C2844CD59CE3E68D5FC9DDE5B /* ColumnType.swift */; }; - 640CCE9C3A28AA3CA15510899F9140EE /* FBSnapshotTestCasePlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E5911145B436332EF43EBBDE7E6CDA9 /* FBSnapshotTestCasePlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 64C86F2C6C930257809E85602113204B /* mem3.c in Sources */ = {isa = PBXBuildFile; fileRef = B879FC7FFD1918AD9A99D212BB3DA7FB /* mem3.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 67091BB18EA8BF6913739688AB7FDD03 /* mutex_wcdb.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F6A82607269E6FB6F472F6C4488DA3 /* mutex_wcdb.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6768219789457703F7523F533EE56CB5 /* rtree.c in Sources */ = {isa = PBXBuildFile; fileRef = 0D2C261220137389577E0E25D9696F66 /* rtree.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 67900475325854AFF252C29C05D69122 /* vacuum.c in Sources */ = {isa = PBXBuildFile; fileRef = 953E4CFA5CA8CCBA3E6CA55F7CFF2BD8 /* vacuum.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 67F1963AA7C9EDB78127AD5F566A4949 /* UIImage+Diff.h in Headers */ = {isa = PBXBuildFile; fileRef = C01B5E0468FB391500B5CE91906AA1CA /* UIImage+Diff.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 6884451BA4699A47772D4520DFB56629 /* pragma.h in Headers */ = {isa = PBXBuildFile; fileRef = A4D0796E3D77462A2F42DF4FD9C5BCF3 /* pragma.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 689851F4B65EB0613B61C6CE8F0A8CFB /* sqlcipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 208CAEC6673B7C0C55E8A260CA2E9936 /* sqlcipher.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 68D63EBF0EAD9C0B890613ED127DBC3C /* mutex_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BD0F700A73E13AE67151D1323421415 /* mutex_unix.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 69C577251E116B8932A0BD60390EF26D /* pager.c in Sources */ = {isa = PBXBuildFile; fileRef = C0E5DF2BD31809E3F1A4018A2E009037 /* pager.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 69DE75BA185BBAB5FDAA28321F3C849F /* ConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4A1138AA274CD1E4839F0548F25126 /* ConstraintItem.swift */; }; - 6AC1B881BB319C89AD023A02CDC8FC3D /* ConstraintLayoutGuide+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C04B27E6710C0E07FB4EEEA8231088 /* ConstraintLayoutGuide+Extensions.swift */; }; - 6BF9474E1C89F2FC2747B70101798C41 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B4C445819691E20C66A3B0C876E8F09 /* Update.swift */; }; - 6C0F4156A4893EC3E705EEF34D5221AA /* where.c in Sources */ = {isa = PBXBuildFile; fileRef = 2AD26611F62EC841B8AA65D6D377987B /* where.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 6E4CE8F3BEAA64D17F48765F8D1B7419 /* pcache.h in Headers */ = {isa = PBXBuildFile; fileRef = 7867ADA3ACBECE3FE0964EB6C2ADF7D6 /* pcache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6EAC8B6FA2D115DE708A58C601DD25E1 /* Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BD359F43CC6E82E7AC095DEFB667F6 /* Constraint.swift */; }; - 6FF0CE70CA7D0F8F4B38C403AEB86B59 /* TableEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 282C9EF12770BB707851C8092FA502B1 /* TableEncoder.swift */; }; - 71E9BDC77BBD4811EDCBD86C153DA3BC /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = A17FFA6423420CF5D2CD5A85C44E4F88 /* util.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 7227932727F5F79EB6CF2F04E18DF2FE /* vdbesort.c in Sources */ = {isa = PBXBuildFile; fileRef = F726DF8A247CF9E3ED50B8EAA5957CFF /* vdbesort.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 7278EB29E9242FF7FA58F3B0B1184113 /* fts5.h in Headers */ = {isa = PBXBuildFile; fileRef = 6828855C8EB1DC703DFC765E3C8E9A27 /* fts5.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 731D27FC388519A4D24B52D2A29E11C8 /* Defaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85D8102D03B9C841FD3EC7FC419350D7 /* Defaultable.swift */; }; - 73A29EA24E5EF12889A46883F1AC2818 /* walker.c in Sources */ = {isa = PBXBuildFile; fileRef = F6A8B52AB6EF90B11566E30055201070 /* walker.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 74339C58AC4E5631FB8C0E662668A796 /* UIApplication+StrictKeyWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = D2B3E35A4BC256533E927EE1175DFF3E /* UIApplication+StrictKeyWindow.m */; }; - 7540E2BE9446FF57C9D2459D20877071 /* TableConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60954761F92EED9592A31A783EC3B05E /* TableConstraint.swift */; }; - 754CF78CC23FE72149AF4CB2E1A141B9 /* StatementSavepoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9F59771C2F07940C3D3E1D3219BEB2 /* StatementSavepoint.swift */; }; - 75A9C102F3A707CD1C58A32620CB97FB /* PrintFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA773D1F7222071AA66218F4A74E3199 /* PrintFormat.swift */; }; - 75B9D189221C4D0E9E306F3006999943 /* os_wcdb.h in Headers */ = {isa = PBXBuildFile; fileRef = 00FE0A814FC0CF97A87C4BF7AE3C52EE /* os_wcdb.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 778ED286F78E0C10F3F7D3B1DD2D660E /* TableDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60871F481FE13AFE0AF788771BD15CE /* TableDecoder.swift */; }; - 78079FE3271F118CE83CFD8D5E4F8C21 /* TransformOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D5FA619E1FFE76299F63EA49B6497C /* TransformOf.swift */; }; - 78BEB406520FC2CBA626639A9F1CE9BD /* treeview.c in Sources */ = {isa = PBXBuildFile; fileRef = E24C10B99ADAD73E210FB8245ED8197B /* treeview.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 792C4E7E6F8093FE273376553AB2A094 /* legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = F63E4EB6FB734F947641DABA8C75AF07 /* legacy.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 798C7D29511D498BDB7BEC4996708557 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB2EB56477F0F500E5E6BC9306CD760 /* Configuration.swift */; }; - 79C7D4E9901AA11C25F8C71F3E9DF612 /* Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE978CDB4DB8CE29F1012CDCB29CDE7 /* Properties.swift */; }; - 79FCA569BCE23251EE345047D3A15EFB /* BTBubble+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5CDB7508D26894D5B12C0A1D125803A /* BTBubble+Draw.swift */; }; - 7AD2DE331157EFDE3B334048A5509E27 /* DecodingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63165FEB321973E0AD39AFA539EBD85F /* DecodingStrategy.swift */; }; - 7B0C68363732FB8C3C91E8549F9BD771 /* InitialModelCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D07A0B1D2259F30D4DB6EA5C979D6D8 /* InitialModelCache.swift */; }; - 7C67CBD15D9B5D0B7769B2F469478332 /* FBSnapshotTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D6B4B87B15CBF895D050929727FBC7F /* FBSnapshotTestCase.m */; }; - 7CDFE1663B1A626E3E036AC1891C7206 /* SmartLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF7058B96B59956D0341D5EE8DB387B /* SmartLog.swift */; }; - 7D9031DCB898CD9DE37C4BD4F3FC550D /* DateFormatterTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4EB0C0E105B37698E256E0C139E5B82 /* DateFormatterTransform.swift */; }; - 8087D4C8588A44C31FCA163A64FF58C9 /* select.c in Sources */ = {isa = PBXBuildFile; fileRef = 15854FC71FC55631BB77E2D925160F40 /* select.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 813AFFFBCBD0388DE6FF1673AAE267DB /* ColumnTypeDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2369A4FD37B12F6C5C3AD86835E5DCD9 /* ColumnTypeDecoder.swift */; }; - 839932B8D304C93ABD76ADE280804E70 /* _SmartJSONDecoder+Unbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C12AEF40FFC99AB7F38B2B64D66EE7E /* _SmartJSONDecoder+Unbox.swift */; }; - 846C97A8C420EFD9B8C4B77ADBB1E8F5 /* TransformType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957AD6E6B2DEA9C2223DBD3581F63EBC /* TransformType.swift */; }; - 847D3774A5E68799F8F05900F07389DE /* msvc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7A0EFE15E507C964CE79BE8AC57D92 /* msvc.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 84A72ABBDFDDC959E298C0107A6C4BE7 /* WCDB-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = 589169F9BA6B76B8D7A16765B1135F63 /* WCDB-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 85913D5AC8449037C282EB84450592A1 /* CleanJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D8501160FCCFA343E417A66AA91DF92B /* CleanJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8721B511F4B2A7B63C56D9CA080246C0 /* StatementUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32588646583AF8336B91EA2A0FB6CD2A /* StatementUpdate.swift */; }; - 875A310EAF4D0C136C3FFFF5E0335BE4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A892CB525DEAC1E1F53B41226E5AFC5E /* UIKit.framework */; }; - 881F121920DBB09F06C15ABFB7715938 /* RecyclableCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FFE7610801F54DFCE0B7C42FE349DB /* RecyclableCore.swift */; }; - 884DB7B8E20C199509BC5B9A17263113 /* BTBubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCD89A8AF7896E1C2C1B554E7A51E56 /* BTBubble.swift */; }; - 893D219E4A343A71C3E305046ED038F4 /* bitvec.c in Sources */ = {isa = PBXBuildFile; fileRef = 67862AEB121CDDE6370187F66B07A7EF /* bitvec.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 8A972E8E412C9318BECC91DCB4ACCAFC /* alter.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B59B3059BFCFF25377D0910E7F11C89 /* alter.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 8A99C5C187ABDD2366D4D3A5A766E615 /* SmartCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B5009BA615F605E4770A0F999C8EAC7 /* SmartCodable.swift */; }; - 8AE19756F0126FE92AF625E36F3D70FE /* UIImage+Compare.h in Headers */ = {isa = PBXBuildFile; fileRef = E9E6026DFD06EAF5D78CF289D189A4AB /* UIImage+Compare.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8B9C123C6DFE8CAA1CF7382D30030372 /* os_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F4A523DD234E18A60AF35F11CB72F42B /* os_common.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8C3394695CB4CCECD873D1384F4BA076 /* Export.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BEE5FD64126C65AE637CAF7B4E236D6 /* Export.swift */; }; - 8C6BDCA05022A1CF38F3EC64EE8E30F7 /* SmartEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95129AD448C6FA92BE25187E54E7D541 /* SmartEncodable.swift */; }; - 8CD5DE204C3C5F6557878ADE2675A406 /* HelpingMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08951D687428D680F5A7D8AA9B6859F5 /* HelpingMapper.swift */; }; - 8D72B695C7EF0186A0C0F1A18F944880 /* PropertyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 782FEEC464789BBF3AB2DEDD778C2B0A /* PropertyInfo.swift */; }; - 8E181742809C6F03AE51D0F6E52E57DA /* BTPrint.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE628DAB731CE9CF30F4A4CA4F2DD41 /* BTPrint.swift */; }; - 8EB8C97A9108E89E0975FFF7613FC456 /* sqliterk_btree.c in Sources */ = {isa = PBXBuildFile; fileRef = 65031BFCAFB9694B1F3F528750789158 /* sqliterk_btree.c */; }; - 8FC9EBE1D9180F97E4FBAF49FC729D3B /* SQLiteRepairKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0986BCD62FBDFF356818F2240DB86644 /* SQLiteRepairKit-dummy.m */; }; - 90087A9E35991CBA33825140C0A58757 /* CleanJSONKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D410A3C5F8C66EF9FB1F780E3A614657 /* CleanJSONKeyedDecodingContainer.swift */; }; - 9040ABAE95AF55340A2FD5A2AE4FB74B /* func.c in Sources */ = {isa = PBXBuildFile; fileRef = EB6F7BA0DB362E9C44D65D67B447711D /* func.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 91D8E61BF918EFAB8EB9FDC0000956DE /* crypto_cc.c in Sources */ = {isa = PBXBuildFile; fileRef = 06654512231B9F787D6A5363A3BB410D /* crypto_cc.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 91EC3B883BA861D9867A5E59D1939BC0 /* os.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E56852052AF5A2DCBC105963F8669A3 /* os.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 92CC91D4B6AF0B3E18068CCFBE36A3B7 /* BubbleTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848CD67E6D3721BE0AB072D0731ED981 /* BubbleTools.swift */; }; - 941BDD932AA35EBA6AF6F399183E86D7 /* fault.c in Sources */ = {isa = PBXBuildFile; fileRef = EC9FF687080036A8654DA415051A4F52 /* fault.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 94F87A9E2D3CE342062B17FFDD03D7E8 /* sqlite3rbu.c in Sources */ = {isa = PBXBuildFile; fileRef = CF59ACCBC088180B9DDF32F0F236A4E3 /* sqlite3rbu.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 955A00E1FE013891C9A33C1E78AA5A8B /* hwtime.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D070A8985C735AB5F1CA1940115E588 /* hwtime.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9563FB84D29C49072BD3D1387C75FF70 /* sqliterk_column.c in Sources */ = {isa = PBXBuildFile; fileRef = 9BC163C89756D7DD71745C9D0ED58162 /* sqliterk_column.c */; }; - 95AA6CBC32B1C295C77C49ED41616A92 /* ThreadLocal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8073B9C0CAD4D26D09EB8F8C618A816F /* ThreadLocal.swift */; }; - 95E194A3AABB5407231E898B6686F73E /* ConstraintMakerRelatable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0B07DBB6CE6B51956B3F9FCE907678 /* ConstraintMakerRelatable+Extensions.swift */; }; - 96C1D1983D7CDA8566ED049A7EDB49BF /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1352FCE3039BCA9739C2333B9AA5EE /* Statement.swift */; }; - 96D8402B4AFC4AC7349F1B487D6EB08C /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074E54E9F3324F34290CCDEE383AE984 /* Transformable.swift */; }; - 96E27528247EE186ABB790A11076678B /* StatementDropTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BF26EB92D747312A7EFF6EB2BE276AC /* StatementDropTable.swift */; }; - 96E88CE169F3257187905A8B21B170BB /* SmartCodable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FE71CAA940B03B2DDA72A6A70DA38BFC /* SmartCodable-dummy.m */; }; - 9780912475549103BE9BACB1C9CBEEA1 /* StatementSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D90EB55E616E8CECBE8918EF6E09491 /* StatementSelect.swift */; }; - 97E088B9850A57B244DF543BCEB18FC0 /* insert.c in Sources */ = {isa = PBXBuildFile; fileRef = 40AFCC5DF480085E54766074710BC33F /* insert.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 98238A99285E5720BDC568359D649907 /* TimedQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D67E5BBBE0B0CE733CE89F049DA3E12 /* TimedQueue.swift */; }; - 98F570DA48370453D648BD526FDAAEAA /* LayoutConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D18D6541EFE81AFDF8F5EB531B779D4D /* LayoutConstraintItem.swift */; }; - 990B0A2658464507A4A8028B2E5D2148 /* pcache1.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FDC79FFAFD807358086B52EA83BF2AB /* pcache1.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 99258493B0865705197B3B2B4DCA39C0 /* malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A5736E278A439A4F84876664433AD19 /* malloc.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 99C3E4EDBE5BCDC161722B105F0FD62F /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F616208225C5B42B50ABA5F5267C29F /* Database.swift */; }; - 99C79FC97E865A2578C62C18939A3E83 /* fts3_hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F05955F92891DDC9863B462D73A04E5 /* fts3_hash.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9A5C397C4B518E59526372CA6AA0BE65 /* StatementAttach.swift in Sources */ = {isa = PBXBuildFile; fileRef = F631CC802E2701AD6DEAB71A9B7134CB /* StatementAttach.swift */; }; - 9A6CCC7BCACBE8218126670E6B08EF9E /* BTPrint-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CC97091BEEC9AAC898E58EC68EBF05 /* BTPrint-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9ACD167B86B801CE54DD75702AC8F224 /* SmartSONUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8153927F031D060140C06D57CFC4A431 /* SmartSONUnkeyedDecodingContainer.swift */; }; - 9B9DA58355282344F0130FDB105ADF79 /* StatementDelete.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF9A5EA944619747B64BF79AEFCAB71 /* StatementDelete.swift */; }; - 9BC98C6A1CCC755C0F366463D6D18C14 /* ColumnIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215B5A8E4B87860917054FA268224A4A /* ColumnIndex.swift */; }; - 9C9548E8B4675954566202F7B87FF0E6 /* ConstraintConstantTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9BFA8B0590A57660EC2A37A517822E3 /* ConstraintConstantTarget.swift */; }; - 9D3B496B64C47E6B1812D22D7385F515 /* CoreStatement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65BEC92F44B8431C10E16C69DE91C591 /* CoreStatement.swift */; }; - 9D3C5E2F56838937146191468A893244 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D28489E1C38C95EF1D07BF0CD0A85216 /* XCTest.framework */; }; - 9E02CFFEFE1BEC978B512286F03D31DA /* ConstraintInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929C4FE20402ECA721BAE7E722B6E523 /* ConstraintInsetTarget.swift */; }; - 9EB699629BD092C03AAE47603E6154F9 /* ChainCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E63D643A1B5C6A2B7C0A46448402CEB /* ChainCall.swift */; }; - 9EF3EE1E656BB216395A6B9F15386E95 /* CommonStatement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E1722C947F1DA1DF228499FC65654C /* CommonStatement.swift */; }; - 9F2B1F18D741C08147B423A0AF2E22DC /* MultiSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C8C2472E4FE52411D856291FE3408D2 /* MultiSelect.swift */; }; - 9F9A6624FA895D076FECBBF61491460D /* StatementInsert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50553FB57F080F1E987A3CD55DE922CB /* StatementInsert.swift */; }; - A03FDA8BC5741880B1EF11AFD248EF48 /* ConstraintOffsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE3301D1CE71A4E0C1D2991CAB2A9207 /* ConstraintOffsetTarget.swift */; }; - A0874622A520C7BD11C273BBE3CE953C /* URLTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B508AD354731149BE19FE9B19292E30C /* URLTransformer.swift */; }; - A0BCC2B78BCA27EFAE901B4406942557 /* BTBubble-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 97D90DEDEA77DAB3CC21506808D91533 /* BTBubble-dummy.m */; }; - A0E5EC9E431A5BD01C4695BC6AE5DEDA /* ExtendCustomModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2131D87E7F2B2C1601DBFDB5E83BD /* ExtendCustomModelType.swift */; }; - A136BAA6B969F9512DAEDBA3CE3AA6D3 /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16BCF96DA4A6F9BAA3D405212DD2906 /* Selectable.swift */; }; - A1714BD98D3E38B7A52BB8DDBF76F004 /* whereexpr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CF668240903ACFCD31E3E022039B6E6 /* whereexpr.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A213CE0BBBBE1F4E97A2CDFF6DF512BB /* opcodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 014B1C0CEA4BF05C07C0E27BA426D4DA /* opcodes.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A23DCC216EC64773E48A293C969964AA /* Table.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D936226781B9F30DC482374790455EF /* Table.swift */; }; - A26B23F738C7F52E17A9F366A4B1A670 /* Tokenize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB4D815AD7FDFA7FE61D12B8DBB2534 /* Tokenize.swift */; }; - A274754305853DD578468EE72BD40C3A /* Patcher+Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345703E7CF3B18DFA38742BF2DAD0EB3 /* Patcher+Transformer.swift */; }; - A2D6CC53EF61C755B77BBFF31B1F0E76 /* _CleanJSONDecoder+Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC98C8117F3B1431C854A9C6B4F8FE02 /* _CleanJSONDecoder+Decode.swift */; }; - A38BEDD3CD86D876272D2BCC70817194 /* SmartCodingKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DDE2047CA2148A5644CFD3E9B61B0C7 /* SmartCodingKey.swift */; }; - A3E3AB7C765C21AE17B1E6EE6560040C /* SnapKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DF9DF1A9D97BEF7AF54F2FEFEE23AE0 /* SnapKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A3FF41BEF6F5F060F350F8EF4EFB83DF /* mem1.c in Sources */ = {isa = PBXBuildFile; fileRef = 04AF682E0F5A9200126922C904DB3A17 /* mem1.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A4119C2934A30FEC8130AE0AFC65281B /* SmartJSONKeyedDecodingContainer+decodeIfPresent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04943FF1F9F4BCCF3A02297282CCAF6E /* SmartJSONKeyedDecodingContainer+decodeIfPresent.swift */; }; - A41DA75BD15BEBC94523902170EDE87D /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCADA2E9A3086D97A8BCB6A43D4E9D67 /* Select.swift */; }; - A51491E2BECD0FDFC6B28CCDE8CAA2D6 /* sqliterk_util.h in Headers */ = {isa = PBXBuildFile; fileRef = F92DEA4DA3E1E8E57E1E048E7AD51789 /* sqliterk_util.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A522DA5E890E3AB1AAF8C7A2A060BF75 /* analyze.c in Sources */ = {isa = PBXBuildFile; fileRef = 2640505E1669FA0E4615AB6C2A07EACF /* analyze.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A578AD0AC1B114DD99F8E8C44E7D6E25 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - A5A8BF973BFE9C9304372A26C9F2E35B /* ConstraintMakerExtendable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186F0AB785FEFD705F9810BF829E3B9F /* ConstraintMakerExtendable.swift */; }; - A5B33904555D4808E08DB75C19622D63 /* memjournal.c in Sources */ = {isa = PBXBuildFile; fileRef = 9150B5DCEC6DD38F143FBDEE388906CE /* memjournal.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A5E849B00E179FB98F3A2CC91378245A /* DecodingError+CleanJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D292372E6836D90D57FB9F067F486A11 /* DecodingError+CleanJSON.swift */; }; - A6225D9957CB15D84B5CAFC52C35C4A6 /* TableCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AFCAB9E9753399E6A58D76D66B7B130 /* TableCodable.swift */; }; - A64D032799685FC978C16E7B31CD98B1 /* sqliterk_os.c in Sources */ = {isa = PBXBuildFile; fileRef = A24DE9EEC0E48E6087452D0991A25DBB /* sqliterk_os.c */; }; - A674A2F3F5F0304A6524F702EA301B42 /* NSDecimalNumberTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C6B2412CFDC619866F34C07873D2D08 /* NSDecimalNumberTransform.swift */; }; - A7761020975300C8127387DFDA142850 /* sqliterk_output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D36CFDC8FE52D5BF5257BBC8979DE5EC /* sqliterk_output.cpp */; }; - A8F9C389534594E34C34B08821D67E42 /* RowSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1ECB4EFC6697075F43D35D69C0F6BCE /* RowSelect.swift */; }; - A97102F4BCB2B5D01BEF6BDDB7065D81 /* complete.c in Sources */ = {isa = PBXBuildFile; fileRef = 1EF0B53B69337F7F4AA44D3A9F9CDE37 /* complete.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - AA545F464B606F381AE7B046F93F2068 /* WCDBOptimizedSQLCipher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DADAE210A27CFC78F890E11F91CDF3B7 /* WCDBOptimizedSQLCipher-dummy.m */; }; - AB0859F40673A83912F55328A3216F7B /* CodingTableKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052C76D3ECB08C7CE97A583A8F4AA784 /* CodingTableKey.swift */; }; - ABD796DECC6774A6A3CFA68A265BFBA9 /* Master.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D753BDFA887910415613027FC5070B /* Master.swift */; }; - ACBC03A430A09775E02C0B3676287DD6 /* sqliterk_util.c in Sources */ = {isa = PBXBuildFile; fileRef = B424B547BC415CB72334DBEE448A4DB1 /* sqliterk_util.c */; }; - ACC2193BDBA2A9F32319E428E9052433 /* SmartDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70B952A2FD0BD10A80C59B2F4BE7F89C /* SmartDecodable.swift */; }; - AD2508F7D92BF2004FF8ACB8A56A22FF /* WCDB.swift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 925381DED7E88D2040106861CAEFE6C8 /* WCDB.swift-dummy.m */; }; - ADC27F881811D6E2247529ECF84FBFD2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - AEDB5D6AD5FE1F510B11F2BDD3DA2335 /* parse.h in Headers */ = {isa = PBXBuildFile; fileRef = 33A1FC38E885F6CAA0517719FCC0A1B7 /* parse.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AF689A467F60DEC470D6E7A919FE487A /* SmartAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A766AE91E8CF4C4930E74AD1BF9210 /* SmartAny.swift */; }; - B03B5579590D528CBA6D11FF638BC2AF /* Typealiases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017E9F0474BFE7DA39821ABE5ED3C7D3 /* Typealiases.swift */; }; - B19DC048E870298A604D3A4191F60CFF /* sqlite3rtree.h in Headers */ = {isa = PBXBuildFile; fileRef = 561BF226C66CCB775EEEF0E42F3E87BA /* sqlite3rtree.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B1CF055222726FC043CB0448D462258C /* prepare.c in Sources */ = {isa = PBXBuildFile; fileRef = C6BABF528CFB1403AB76736DC9D8A507 /* prepare.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - B26F8523031ADC544BF2707EA4F81778 /* vdbeInt.h in Headers */ = {isa = PBXBuildFile; fileRef = 665EF7716439F0B62542010899E7BC02 /* vdbeInt.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B38BC5C353A00655022949C608D4C10A /* expr.c in Sources */ = {isa = PBXBuildFile; fileRef = E4AF1DDFA0BFD4D141DC95A23E60E21E /* expr.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - B43017FEC99D227D4CDD81DD2C27D9D9 /* ConstraintMakerPrioritizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28D7943409E3C2F68D7F7BFD3C05A1C /* ConstraintMakerPrioritizable.swift */; }; - B4AB5333566AF99D8865EAE0427DE941 /* sqliterk_values.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C3826A17E7079B5E9B8EF5E0726A8B /* sqliterk_values.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B52281F9F4340D4FC8ABB2FEB1FEC08E /* UIImage+Compare.m in Sources */ = {isa = PBXBuildFile; fileRef = 6655E8C804740DB2886BEC041DF12E7C /* UIImage+Compare.m */; }; - B602241CEAB9B07F7156F3235077F8AE /* vdbetrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A66148DE9C1A94AD684B306C4A2F0C6 /* vdbetrace.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - B6E9C613E8F15FCA36E4D4AD741191B4 /* ColumnResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07024BD00FC36634A74C70568308AA01 /* ColumnResult.swift */; }; - B752F7C4BECB65894B1F49421049CE5F /* ConstraintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A0CDA24DDDB701970130A91AE5FA140 /* ConstraintView.swift */; }; - B78B71D59862B636ED6F920A0B25C65D /* Handle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E966EA41E66C041E21596A3772AADB3 /* Handle.swift */; }; - B84A210D9E34CB1B5308070B7EF3DEA8 /* SmartJSONKeyedDecodingContainer+decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FBCD4D36359C93A5A40BC3BDEF2CD0 /* SmartJSONKeyedDecodingContainer+decode.swift */; }; - B8F2663637A011291A4B2931410C401C /* rowset.c in Sources */ = {isa = PBXBuildFile; fileRef = A352B8E7226498116372CB1AD0618F54 /* rowset.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - B93F5B04FEE1DAA927A1E948C601CC88 /* mem5.c in Sources */ = {isa = PBXBuildFile; fileRef = 4456F7D1572273D7A8579F5AC4D14E2B /* mem5.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - BA3E240FF7C7BF3E385ED6DC89345EFB /* Pods-SmartCodable_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6021C11E2C3E5FCDE30179E13E0E6452 /* Pods-SmartCodable_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BA4515FC4EB42075B545BC136AAF21C9 /* StatementCreateIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAA9762BFF90942F2F387B26557AA5 /* StatementCreateIndex.swift */; }; - BA8576EA4A18EBBBB8A88175FA55F2B0 /* StatementRelease.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AE97353C403B1B353D4887A7644E854 /* StatementRelease.swift */; }; - BA981BA87F28FCB8445B5218A9A14CCA /* DecodingError+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D9E45948CEF9BF9077D26412102B6F9 /* DecodingError+Extension.swift */; }; - BADEFEFE78C547F20032D251D25C3031 /* sqliterk_column.h in Headers */ = {isa = PBXBuildFile; fileRef = A361C5D364F6A6DA615D350869696116 /* sqliterk_column.h */; settings = {ATTRIBUTES = (Project, ); }; }; - BBDCCA2C3EA47E20E98B465C3D2EFCCE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */; }; - BD47CB74CD9B2B4D2D942C9B65748DFB /* SnapKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DDA253A371800B761863D370EB8DA28 /* SnapKit-dummy.m */; }; - BD90F922C39E6EAEAD85EBD1F2363841 /* CodingKeysConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 815ECC31D5B46D1C6B8D579980A78AC2 /* CodingKeysConverter.swift */; }; - BE432D00488E08C853DC689BE24C54F4 /* HandyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4711916E7B6BC9EDCEB84C83D65ABE93 /* HandyJSON-dummy.m */; }; - C0828EC388D79328143D139A1E023556 /* loadext.c in Sources */ = {isa = PBXBuildFile; fileRef = D987A5E4DDCE06D16CADF70907060EC5 /* loadext.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - C15639E30DB10370C7026D5AE0C5431A /* Declare.swift in Sources */ = {isa = PBXBuildFile; fileRef = E871449A711764164F5DF40EE5109741 /* Declare.swift */; }; - C2881F0D6A914D4337B1226D3918A70A /* fts5.c in Sources */ = {isa = PBXBuildFile; fileRef = 51A93FC1E25AF66C3E9C18D8296E36B9 /* fts5.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - C390C6005353FB986CB52F474CEF8588 /* FBSnapshotTestController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BCF255A8D93A5832ECBCCFD5006F2EA /* FBSnapshotTestController.m */; }; - C3C8AE028E321A1A3A72FA2C94995B01 /* SmartJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54221FFC83764C52FD659D644D6F1ED8 /* SmartJSONDecoder.swift */; }; - C3FA32D5F4FC84BBDFD2D57DAECCC18F /* IndexBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2E09890770921E19347954E8967E50 /* IndexBinding.swift */; }; - C586C8D0FD36B229773544DA032D4983 /* Pods-SmartCodable_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB62CDC1D9A84669428234D73C264AF /* Pods-SmartCodable_Example-dummy.m */; }; - C586DC95274CF5AABAD935AF549A8FB6 /* BTBubble+Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4003C2B584F6E186819D97CEB2E63F46 /* BTBubble+Location.swift */; }; - C66CE960C72934795BBEB480C5094477 /* SmartJSONKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F628734F4AD8AC92C14058127679E7F3 /* SmartJSONKeyedDecodingContainer.swift */; }; - C6E090B7A89D40489E53D4B5B48EE191 /* WCDB.swift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 593175FB6C4DDBC7DBC7DAE352763FC2 /* WCDB.swift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C7BB5FDD6E9E8784CE15BD0611FD1373 /* Column.swift in Sources */ = {isa = PBXBuildFile; fileRef = 080B01573DB252F29350F0BEB393D939 /* Column.swift */; }; - C816257A0FAB5DB746F7BFF1EA4CCF3D /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B318245EAB932A9788ED4E4D8564AD0 /* Config.swift */; }; - C84D4E3B33D929FD0F86B5D3AE4AADE2 /* StatementReindex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57420310DABA9A536A9A0996B4DFFD11 /* StatementReindex.swift */; }; - C890E34038ED089EB9ACE34DB931C248 /* vdbeaux.c in Sources */ = {isa = PBXBuildFile; fileRef = 36BB093C85AFBFBE00809739200019A5 /* vdbeaux.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - C920144CE195D2198DAE63F2D976AADB /* HandyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0110482CEAC61185104B0F2A20BFB4B6 /* HandyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C9F76407497DF0205D7460B36D22259F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6FC37377401182941FFB20A1035A933 /* QuartzCore.framework */; }; - CA408F2FB0811B1B2DEDCBD4949EA6D6 /* vtab.c in Sources */ = {isa = PBXBuildFile; fileRef = B753815544AFD5C6E0EBECDBE87DF183 /* vtab.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CA54C09A12400567AFFCB407EEB7E154 /* UIImage+Diff.m in Sources */ = {isa = PBXBuildFile; fileRef = 208BD4FE2601BA95A308D031441A72C3 /* UIImage+Diff.m */; }; - CA5FB3C081CA09363078DEE45C8B6C90 /* WCDBTokenize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75DD762DA8418DC60C817DD56DC3E353 /* WCDBTokenize.swift */; }; - CA997421613DE4D0A8FBC166BB3EBC50 /* queue.c in Sources */ = {isa = PBXBuildFile; fileRef = 8DA4771CF91F3004D3D65B79990DE177 /* queue.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CB4CFD223A869C96E4B943C182793DC9 /* wal.c in Sources */ = {isa = PBXBuildFile; fileRef = 6FAA1DBD66A24E9AC890DC3D6119D2ED /* wal.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CC6E67AE1352C3E8E9F3900EB2B4D478 /* global.c in Sources */ = {isa = PBXBuildFile; fileRef = CC539335DC60778548E801CDB7F2D02F /* global.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CC89AA019D8C987A06DAEA893BD2182E /* mem2.c in Sources */ = {isa = PBXBuildFile; fileRef = 02F1F533ACB6C749844E6C51143FD7CC /* mem2.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CCC3DB9F2FEF5E50AF40EADAC26F72C5 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72D10260E32B90F95F2E7373E81C0C4 /* Transformer.swift */; }; - CCCEE128C2F395CE7E3A13D343BC350B /* BTBubble+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47AFB782E50452241E979C069CCE7C93 /* BTBubble+Animation.swift */; }; - CDEA17A2C8E2D5F50C6E60D4E1B292E1 /* threads.c in Sources */ = {isa = PBXBuildFile; fileRef = 40A09FC531CEBD255071D71F9AA1FD3C /* threads.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - CE77259DDCC2A6C2DDE78504F3A694FB /* ConcurrentList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78CD18F607C4C7B3260A2086E6FA71F5 /* ConcurrentList.swift */; }; - CF7FAB0C5D474E379798F82E5DB4092B /* ContextDescriptorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA6C3D31D4A4A55C19A9EA22E0F3C2A /* ContextDescriptorType.swift */; }; - D0E1AB8968931EFB9C5D2FC9A61C84DD /* ColumnCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49B1E6ADFC78844B1A8F500C06976E2 /* ColumnCodable.swift */; }; - D18A66A416165B614EA8DC0822552D02 /* HandleStatement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 798614252B284BD86026E6391A1D6B83 /* HandleStatement.swift */; }; - D1D8776BB9B31588D346223BCD51C175 /* _SmartJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E81302FD66DAE30D32CDED9F8F953D9 /* _SmartJSONDecoder.swift */; }; - D37F777D759D29E1F7323611B01021D4 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A6BBDBDEEF349AAA722FA356CBA7BD9 /* main.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - D44A699BB95F3FE62CE11178D7E7C1A3 /* fts3.c in Sources */ = {isa = PBXBuildFile; fileRef = 20EFA042731FA1BB8CE1D3B3CA1DB012 /* fts3.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - D4E5BC7906B48C020613918044DC8CB0 /* whereInt.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D41F501030CAB0211BB226AD82F40E6 /* whereInt.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D5A7220BD8FEFE044AA6D6EA87E72F00 /* StatementDropIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBD193AEDCC1BC474026921C4493237 /* StatementDropIndex.swift */; }; - D7834825B2690D47A548E5BADD90B54C /* Patcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09AE90122BA076289207672D92C0950 /* Patcher.swift */; }; - D79C863A2581DB4910306B5898CC9B9D /* opcodes.c in Sources */ = {isa = PBXBuildFile; fileRef = 58EA21B6E71EBB420FCB0D177FFC3B0A /* opcodes.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - D8DF962A965B6C7B0CBCAC660C86577D /* TableConstraintBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC0D345CD33B982912326FCB76C211C2 /* TableConstraintBinding.swift */; }; - D97C3A1A45117372E374C9AEE0EF9C0E /* sqliterk_crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 43E555ABFE305E012A37237BC940803F /* sqliterk_crypto.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D99F0E445BB07122CF9EFC990964BBB9 /* Insert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 189DDDBFF6D76C5E4E736A23810B2BFB /* Insert.swift */; }; - D9AB41F2BB09E85EB79CD789ACB3DBBF /* os_setup.h in Headers */ = {isa = PBXBuildFile; fileRef = 36E64B194309465F02BCBBB4DFC42F58 /* os_setup.h */; settings = {ATTRIBUTES = (Project, ); }; }; - DA52AD11094509917C1522D54896C06E /* StatementVacuum.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADAA91299769BD42F20D8F8CD7793220 /* StatementVacuum.swift */; }; - DA79E90A2C23D0DA7C8294C355F9F91C /* crypto_libtomcrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 6FFB72C4FC2D499DF9218B70627E31C1 /* crypto_libtomcrypt.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - DB3E9FEC1A0797427ECD0DED434EE8AA /* IgnoredKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8224719BF93802AC51382B196A6B30C5 /* IgnoredKey.swift */; }; - DB8CC3D34DDE6C093F96E9356C93763D /* Delete.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC0F420686D5E03E5291BD62C6B6F99 /* Delete.swift */; }; - DC22D5FD2A5DE86226E0457F31E9C92F /* userauth.c in Sources */ = {isa = PBXBuildFile; fileRef = AD44D95A3B0AA90BECF82F884FAA3C5A /* userauth.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - DD31E7350864163520D060B45194A91D /* SQLiteRepairKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6866EE8AA2F1FF8308B5C3410AEA8C40 /* SQLiteRepairKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DE13D920EE02866495C19B6484C998DD /* BTBubbleConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC652D711B63F8C1721F16CB2979AE0B /* BTBubbleConfig.swift */; }; - DEDE79F24C29684E5F3AB33DDC0EF63F /* Subquery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D613F035701597084E06D383FA66CB /* Subquery.swift */; }; - DF0082F24CE4296BFFB3EF5FADE3ECA2 /* wherecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 5198AB42A90C8765E2052D192FC434CD /* wherecode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - DFB9F2DA1A87F0A1A02C6419A1CCDA9F /* table.c in Sources */ = {isa = PBXBuildFile; fileRef = 59E469590BC9F29B51275D3ED6913071 /* table.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - E0C538B8B9529B46C9F0F08BE0C9A842 /* attach.c in Sources */ = {isa = PBXBuildFile; fileRef = E554DEBB8837193A575EA37F69484063 /* attach.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - E0D595792CD84F104894E16543C642F0 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 234332AF7FFA3F89DF56548B0498751F /* Lock.swift */; }; - E14F3E3E66054690A6434A5C5B1FB68F /* utf.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A64B6A3CDB35FD693AE7CC214BED1B7 /* utf.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - E222ED79C3BB38A273543B2D2B4D1013 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = A0752EA93024C04D691ED9C4C27314C9 /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E240EACDE1A9C4313DABBFB7FD401BCE /* tokenize.c in Sources */ = {isa = PBXBuildFile; fileRef = 325544FCE455196B6F391EE9FFEE5DD0 /* tokenize.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - E2EF09A2D0A87418F0628B2CFAD304D8 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4268C0E94A4D1CEA5A9AFA2C42E291 /* Metadata.swift */; }; - E2FC31BFAF48F12CE9F6AD9867388A1A /* OrderTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0578B106653292AA1BCD11BC78ECD48 /* OrderTerm.swift */; }; - E4E4787C45F1F154EE662AD931FE9CB0 /* Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7730B02FC8DBB419EF7E5DD4C7069878 /* Interface.swift */; }; - E575B18F4B8BB30FF19D91B1D37E661E /* LogContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 242B3038A4DB16F77DDCEDDE83743BC5 /* LogContainer.swift */; }; - E6B73B0F8C83B587483D0C1E9BA6E813 /* keywordhash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2995ACAFEB77466B338AF49949E0F10C /* keywordhash.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E7035A074129575E62A0136DD93D8E8F /* DateTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07518FFD2D8665D6174ADB9E47C25D2 /* DateTransform.swift */; }; - E710A550162879CE918FC411CF567789 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11E4EA8972278437BFB8CED63ECCD00D /* Logger.swift */; }; - E802B410A260F85C50E7304C8D90D1BF /* ForeignKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 901AD1CA40244E43697CA8525620F3B2 /* ForeignKey.swift */; }; - E98DC8FB2578E76A812E0C94BA10E1B1 /* ConstraintDirectionalInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBB539F9E04B803B7BA7228A07C5BEC /* ConstraintDirectionalInsets.swift */; }; - E9EA02CE0BE621BCFDCCF7AA66CE84EC /* fkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E5130A0E082DB74881AC7C0818F8965 /* fkey.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - EA62F44B607D3025B0D838D1E6BCDF04 /* fts3_tokenizer.c in Sources */ = {isa = PBXBuildFile; fileRef = EC269ED89F5E95338D486A4341D130E3 /* fts3_tokenizer.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - EB6A3BD0F279EE1512529B050348A725 /* DateTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22EEC6388F35D221D7E345FF0D771E29 /* DateTransformer.swift */; }; - EBE77754FCDDCD5520489E15C7AD435D /* parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 7095CF12D4A8623FA91F06BD720560B8 /* parse.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - EC5CB815B7B870B9ACD5EE567BF33DAB /* Tagged.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73913468036FE8ADDE2D7B47A50BB4C /* Tagged.swift */; }; - ED71E932B7F30AD7CFD2A04968A2B5CC /* CBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39158D4DDE62D27C5D0AEEDEBE7271D1 /* CBridge.swift */; }; - EDDF5EE6A8B400B82725B26D5F9D1EBC /* ctime.c in Sources */ = {isa = PBXBuildFile; fileRef = 1D697FCDF8A877E72AE4E548CE2110DE /* ctime.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - EEFF0A57765CB734CF01868904F56DA7 /* HandyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 7009D451088814BE5B398BCC801037CB /* HandyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EF21586EC3DFF6097A58EEC87376A0C1 /* ConstraintLayoutGuideDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70EB956D11844218C49F91382D5686BB /* ConstraintLayoutGuideDSL.swift */; }; - EF39224E16AAA9ED26CDA0C9C77EA658 /* os.h in Headers */ = {isa = PBXBuildFile; fileRef = E4CAFE90E23A817910BA25BDC1390D64 /* os.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F00096B4E2DD0B1EEFAAB8E630A8EF0A /* sqliterk_btree.h in Headers */ = {isa = PBXBuildFile; fileRef = 186D22B5F301661D7D43BA272978F548 /* sqliterk_btree.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F009F0C1E88861F79097F71D7C0E8B21 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35874CD3E2284E8C73B3DF226CFAFE02 /* Expression.swift */; }; - F07986C1C130CBD0B46BB8AF5453A0A4 /* ColumnConstraintBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E3A3F838435552834A4D0E6C267929F /* ColumnConstraintBinding.swift */; }; - F13E9D5DE4C7A4ADD067181C5A737608 /* crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = C0CCC34D442A08D6E9FEECCD26D1E3B7 /* crypto.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F16D0BB1231D60CBF7B3AE25B92D0D74 /* EnumTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14C767AB16373063799E33054D23146A /* EnumTransform.swift */; }; - F177C4754DCBE6015F3F4E2D7DEB89A0 /* ColumnDef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6900708CD940876C68B468F9E43E35B5 /* ColumnDef.swift */; }; - F22287A421E09D8A9D13605580F74C49 /* SQLiteRepairKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = ED36361B8D8564C73918F7F46E942300 /* SQLiteRepairKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F2FE85399D53E6885DC43F57304C6BE6 /* fts3_icu.c in Sources */ = {isa = PBXBuildFile; fileRef = 820888330A2D426AAA53548B20928AC6 /* fts3_icu.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - F3B5B07B5B37CB65300AAD60D9512B8D /* StatementExplain.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15E404E75C9D493CD986005D7C5E51F /* StatementExplain.swift */; }; - F47FA5DC0D1BD01F21FEE05C02A165AD /* _CleanJSONDecoder+Unbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7F41D39907C3886957DEB2668992022 /* _CleanJSONDecoder+Unbox.swift */; }; - F68E491252989FD39243D0BBC13F67CF /* fts3_porter.c in Sources */ = {isa = PBXBuildFile; fileRef = 73713A6806AC55107EA83D93F777C0A5 /* fts3_porter.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - F707DBE0EE06CC294CE67A076E970012 /* FundamentalValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48E65E8527303A5A1758E602CBFD988D /* FundamentalValue.swift */; }; - F7425A58E24926CCAC413F85D403B9FA /* FieldDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CC74704F393D76FD2165D29F8C4069 /* FieldDescriptor.swift */; }; - F7C0960CEEB8F0C18F4503B405EAC08F /* ConstraintMultiplierTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF0FA79118EA6C707BFE21F070594989 /* ConstraintMultiplierTarget.swift */; }; - F84C542CC3B553CA80228877E02D88E3 /* ModuleArgument.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC50E104171DCA96B772A10AA0564122 /* ModuleArgument.swift */; }; - F8A5B347DB74B84AEA04F53922905893 /* Patcher+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3237B54E492CA6E8870521CDD3F613BD /* Patcher+Provider.swift */; }; - F953AA9104BFE0C2DAD639EA60104A75 /* ConstraintView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC8E9C700F20DBFB07454F509557FF17 /* ConstraintView+Extensions.swift */; }; - F98E3202B0021DC8B2DB77256FBE5DD3 /* ISO8601DateTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAC6A3BDBBBA93A2573EDA5CD4CB7FB /* ISO8601DateTransform.swift */; }; - F9CF3D400285C0D58996939F543DBBE0 /* fts3_hash.c in Sources */ = {isa = PBXBuildFile; fileRef = CFCDD063DFADDF236ABB25163EB4A195 /* fts3_hash.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - F9E696447A065C063BDBD133CC0FA0EF /* sqliteLimit.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BAF3FD2C70B49834F7EC00332581CE7 /* sqliteLimit.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FA4062E6B60F8C9FF4DD32907C22B29A /* mem0.c in Sources */ = {isa = PBXBuildFile; fileRef = 611CDA25837467E463F32A67A9EF9FF6 /* mem0.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - FAA41F3956549234B005B298A106675B /* LogCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57205A5656AF71CC52D58B1C38172870 /* LogCache.swift */; }; - FAB03959C2357E325B19E08BC4775DAB /* ConstraintMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35C9C2671C107A19B97A31FB4CC5BEA /* ConstraintMaker.swift */; }; - FB405ACA823DA84B63E53210C7327C35 /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B17CFDDAB4B7441B376FCCB678C499F /* Transaction.swift */; }; - FC135EE0D06EC79DA984EEE013A50210 /* fts3Int.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F14A4BF349F40CAAB558A775EABD9D1 /* fts3Int.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FCCCE88FD3EAFE4AFF179F53A9D5672D /* ColorTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EBE6B1394A862F1ACAFA1EE0AE8D24E /* ColorTransformer.swift */; }; - FDD099F058BC0E5A3A78E4FCEE43A079 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = CE826E7F05CF3F8586C677CB5A2530B5 /* random.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - FE2D1B265D2C1BA0588B9D60480058D6 /* StatementCreateTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE9165B4A6C85359A6DCFB5752AF15C /* StatementCreateTable.swift */; }; - FEE368E42177BB460ACE0A3122223FB2 /* WCDBOptimizedSQLCipher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F83AA16D87731A9D1F4DBD9B22E0F7B5 /* WCDBOptimizedSQLCipher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FEFE2DDEB18C3D76F500C974F166CD53 /* CaseDefaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0269A1B2522AF958CF8C0F8F70F0621A /* CaseDefaultable.swift */; }; - FF2FB2EDD6A5B73BA83F8ECFC6B565DF /* vxworks.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B4B1A682E2866B6A4A07E9208DAA3C /* vxworks.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FF8307B7346F4D3BA13C11AECFE6EDD0 /* FBSnapshotTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = EC222A9A63C304EB2AA02877164C9C90 /* FBSnapshotTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FFAD5D6391D0861FF259F40A208F081C /* sqliterk.c in Sources */ = {isa = PBXBuildFile; fileRef = 9D577565B80212CC59E86358A09119B1 /* sqliterk.c */; }; - FFF9A5D04B0FFA58870DE24722039326 /* Recyclable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644177FA36D4B8A4E563D29BDA08DFA1 /* Recyclable.swift */; }; + 24658CFD39BCB4586D56C427F8EA751D /* BuiltInBasicType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6822011E346FDFA44C5A0CAB94482 /* BuiltInBasicType.swift */; }; + 256558233B40ACA6818F143BBC5B8017 /* ConstraintViewDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C958AC7215CB092EEC6FA33BD843AC29 /* ConstraintViewDSL.swift */; }; + 2588B6538C39C0F91704795197CA6A3B /* SmartUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAACBE9FC72DF06355302EE7B3A730E /* SmartUpdater.swift */; }; + 2878735FE61E1EEB4C493A8B8ED3DCAC /* EnumType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC81D310210EE3584DF75E7C318F9318 /* EnumType.swift */; }; + 2975A09730FD83DC0897129A11EA6585 /* SwiftSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 992A16CABA4C83CBEACADDABDE5021A8 /* SwiftSupport.swift */; }; + 2B88C28DD20CBFA7B3AEB21A365197FE /* FBSnapshotTestController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A29F6A0D45AF40A67824A0487C3A989 /* FBSnapshotTestController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2C16E71C31FE60E1F5DB7FD9D5E56E12 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 2CB61F6FA511CAACB43A50DC3A82E0DD /* UIImage+Snapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 02B734C740F66C4CA7D3E58A2E3A71ED /* UIImage+Snapshot.m */; }; + 2ECCAC52EF4C74E1032E0BC646BBE5B9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 2FCA83552D94DE096535B686ADDFEAD8 /* LogItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E7CEB1D2A3A5C0DBB12BF8FC56CB8E /* LogItem.swift */; }; + 302638AD965D971A268A2114F7742607 /* CleanJSONUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39B2DBA2FFE481C74723D3D77C1C4151 /* CleanJSONUnkeyedDecodingContainer.swift */; }; + 309C54EC9536180B960B9CB8EBD412E3 /* CustomDateFormatTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADDD58F0A7F5CBCD84256A572196E486 /* CustomDateFormatTransform.swift */; }; + 30D475DF57C0C682A723231E7BCA0D14 /* FBSnapshotTestCasePlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = B3CC75B7FCBD0A88F04962B84E46D054 /* FBSnapshotTestCasePlatform.m */; }; + 317E81440B4BFD37C04396CF32DE59E4 /* SmartDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B17DBF7CBD3616A875D3281F35287EA6 /* SmartDecodable.swift */; }; + 31BBDE6D8EF669C30F5140D8058DCC76 /* CleanDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F06552F963B43848600AFDC8043A19 /* CleanDecoder.swift */; }; + 31D6011D9AB3D1D13B504508D6CBD0C9 /* JSONDecoderImpl+SingleValueContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C00DB4F15575B9722480D9D45738DD49 /* JSONDecoderImpl+SingleValueContainer.swift */; }; + 33BC540DE351661FAAA24950E165D4F1 /* MangledName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B6AE0B9AEB52789C2BA9C70151E337A /* MangledName.swift */; }; + 33D8000A56DFDAAE952C15DE08107022 /* Patcher+Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A698925A05268E73A17E232B6FB6FAC6 /* Patcher+Transformer.swift */; }; + 3541054BDBB8790FCC7E74D387B59884 /* SmartEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E44B798553A3E18727230F8D89E3F9 /* SmartEncodable.swift */; }; + 361EA7ABBDD80F154DDC208D9CE920DD /* Deserializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E274A3EAC25DB6D5C25C3CBB604248B /* Deserializer.swift */; }; + 3660B4F629053ABC3C1DF69366770289 /* ConstraintConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077FF679DE0A788D695D32FCF72B1002 /* ConstraintConfig.swift */; }; + 36A5D7A3D1EE0A7C83ED537C7E427ACD /* DateTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ADD33B297AB30B353CFB5D0A4234E39 /* DateTransformer.swift */; }; + 373413256658309F9053CE22BF62077E /* UIImage+Snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 60B0F726C42000735EC1B76226554746 /* UIImage+Snapshot.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 380F4FCB4A16A8BEE8C65EDDA025FEF3 /* _CleanJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ADF3C4B3DE46FA90A67725C575E757 /* _CleanJSONDecoder.swift */; }; + 38B9D58E94D9C1CECD7E381C64A2329D /* UILayoutSupport+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F3C77A10532266D4C2017D4C5657D22 /* UILayoutSupport+Extensions.swift */; }; + 3A030CA5A4DD41F59802F907A93F85DF /* HexColorTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F93E9634821D816540140F7E1D6199 /* HexColorTransform.swift */; }; + 3C53583CB1A5F4926491D8838F580074 /* BuiltInBridgeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E920302DBA2124AFF869243E5CB6351 /* BuiltInBridgeType.swift */; }; + 409FF499AEF8324ABFBA13C7A68D6349 /* BTBubble-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAE8816531C7030F85857D829CF295C /* BTBubble-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 42B6ACFCF650183030867CB3EF345E95 /* ConstraintMakerFinalizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1035777F9D0FAD25F91B78CF571685 /* ConstraintMakerFinalizable.swift */; }; + 440B40432B89ED5D2CFD28D7D9500393 /* DataTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE716DB85C8936F875B13305FA42C410 /* DataTransformer.swift */; }; + 4544781E2299B71D125A0404038166D2 /* JSONValue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA1897EAAC2C936DF3C2195D9388328 /* JSONValue+Extension.swift */; }; + 463073AA2E32EA2F7D5B208B713D828B /* JSONDecoderImpl+KeyedContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91432EF00E1AB07F6B570628BF9725A7 /* JSONDecoderImpl+KeyedContainer.swift */; }; + 46BD19D7708E8AAA015506480ED796A5 /* BTPrint-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 926AFEC77F93BCAD652BB781C5D0AA8C /* BTPrint-dummy.m */; }; + 4AB42EE20602D1A2D43EE5BA223F2DD0 /* DecodingError+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95214B05E868BF779E006FD88F1F0B9D /* DecodingError+Extension.swift */; }; + 4BAD99B7394E225CEDBF94B8100BCC7F /* ConstraintRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 464FF18D590547BE7F4826907AFFE76D /* ConstraintRelation.swift */; }; + 4D9E3A4C588EA10E1B072DD95DF150E9 /* CleanJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A370EE4D019ADFE65F2DC1FF9EDBA187 /* CleanJSON-dummy.m */; }; + 4DA72FD7F1FB2C0449EDEF4B8A579807 /* ConstraintPriorityTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DBF99060B70E1B6830A780BA2524ADA /* ConstraintPriorityTarget.swift */; }; + 4F0BC340FCCD023F7F352325D2B22E44 /* SmartCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55017ACE8DE4C20B38E0C7802356E9C6 /* SmartCodable.swift */; }; + 4F6C6CD873CC992A848865508C54A9A1 /* JSONDecoderImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89E8087BFA786A66175CFC23BA8FF12 /* JSONDecoderImpl.swift */; }; + 5380454C48A12A6E376122ABD8096968 /* ConstraintDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7570803E9622B6523B3325B01B79E44B /* ConstraintDescription.swift */; }; + 5558B876B579BC1E79BD3D2B19148329 /* UIApplication+StrictKeyWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 233DAEDE45A5CF0A47B6462C8C9F92B4 /* UIApplication+StrictKeyWindow.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 55E51F45F1E157D3B4942BA7252C277E /* ConstraintRelatableTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1F4D4D87CBE3DA68AFC92D6F05636AF /* ConstraintRelatableTarget.swift */; }; + 56A72F6D13D930C4A2568F24DEA33C8D /* ConstraintLayoutSupportDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F043A0A52D038042BE4B2E250F39C46 /* ConstraintLayoutSupportDSL.swift */; }; + 56AC6DC6459AE47E7BC4AF06E5B148D2 /* ConstraintDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF3ACF04599EB1C214870D993C7153 /* ConstraintDSL.swift */; }; + 56CAC06DB79E51F4ED416927D57C79A9 /* Measuable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0C0E237F70C307DF23B940F50265F5 /* Measuable.swift */; }; + 595F6DC1BACD0E22327532D6DD9E1E93 /* Patcher+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEB73C0BFC8A0BCE1F336584FF0D0236 /* Patcher+Provider.swift */; }; + 5A8FAA2FBC1E5BC5F5137CB211218A1E /* CleanJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06E31B883A63C5DE4A5A6308F36C8F /* CleanJSONDecoder.swift */; }; + 5AE344B70F964CD3F24B43A406D61965 /* SmartKeyDecodingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD1B40612B0CE612E816E472F043F2F /* SmartKeyDecodingStrategy.swift */; }; + 5AFEE2EFAB9F1F62CCB3D12DA9FCEBAE /* Cachable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B7CFF9C9E99F6CB429445432536C7C2 /* Cachable.swift */; }; + 5BE525FF6FA14B999ED2CCC0AA4FA0CF /* FBSnapshotTestCase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B9E9FCD5E63CE808B8773D040F1E2BA8 /* FBSnapshotTestCase-dummy.m */; }; + 5CCB87A1A86D7C03A5D678B262B37071 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + 5D0C8EE39661E929D4881B314AA90123 /* ToJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9121AADFDAA9E940775A36390D6DDBC7 /* ToJSON.swift */; }; + 5D36B99F3CAB1FC7337082D9581FECA6 /* Debugging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 418DA1AEA18C4A4A1E5D84FCB60DA427 /* Debugging.swift */; }; + 5FCE0936FD3B817C74C1EB6B26D459D7 /* BTBubble+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A4470686F2D00D08E538160531B64E /* BTBubble+Menu.swift */; }; + 5FD7858E6AA15774EDCD172DFE731D66 /* JSONAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2453FB81C81C62905E16C3FD41C15D /* JSONAdapter.swift */; }; + 5FF5ED34372D682A95644DCC006F2E0E /* SmartCodable-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F593D03921D2C6F913665801765ECADC /* SmartCodable-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 604D3C93C17978C23600EC415949AB64 /* ConstraintInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45DCF5151BEFE9D3018AFB99FE8F580F /* ConstraintInsets.swift */; }; + 611CEF7FF1EF9EA1BCEF6C73EEE3ACCF /* ConstraintLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70E88BDB3FDACE8F2B23F3247435107D /* ConstraintLayoutGuide.swift */; }; + 61FCA0616CE6512DCA67D74562D6EA1D /* ReflectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF69AF530FDB1A1819B8E00A3E4775A /* ReflectionHelper.swift */; }; + 62A19B6E867B83058B1C8A2138EA7C50 /* DecodingCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFEEBFE7C3F6CA97EC2C91D3BF3AA9B /* DecodingCache.swift */; }; + 62C1A489E5C6414819815F3219B52FE8 /* URLTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510325960A63C34B69B7173F76A69109 /* URLTransform.swift */; }; + 640CCE9C3A28AA3CA15510899F9140EE /* FBSnapshotTestCasePlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 87EF2DCAFAACA539DB4A58A75FC36303 /* FBSnapshotTestCasePlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 673D9C81275141127A8A2774BC595B26 /* LogContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E62D2D77DEED3B201DFDA0618E0E9D /* LogContainer.swift */; }; + 67F1963AA7C9EDB78127AD5F566A4949 /* UIImage+Diff.h in Headers */ = {isa = PBXBuildFile; fileRef = D283527F80A00FBB2FF5776A4E3B27B2 /* UIImage+Diff.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6873423A671225CBD04F0A29E0106C93 /* ColorTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAB40FD80A45A7E3594DC159F7D54B6 /* ColorTransformer.swift */; }; + 69DE75BA185BBAB5FDAA28321F3C849F /* ConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05DE8DDCC94E79120DAB11B9DBD24069 /* ConstraintItem.swift */; }; + 6AC1B881BB319C89AD023A02CDC8FC3D /* ConstraintLayoutGuide+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE456287EB50E4B04F1A29EC19043B7 /* ConstraintLayoutGuide+Extensions.swift */; }; + 6EAC8B6FA2D115DE708A58C601DD25E1 /* Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD91016CD3E4DB108E6B6B782539B2EC /* Constraint.swift */; }; + 716F32806E27B9ECBB08DFFEF04F0687 /* _SpecialTreatmentEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E248320C9CBA206187879E5FDFE4C6 /* _SpecialTreatmentEncoder.swift */; }; + 721D749F257ABA46950E7187EB42D00E /* JSONValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EEB810E2BEEE8D6FDAC45521E2B95A /* JSONValue.swift */; }; + 731D27FC388519A4D24B52D2A29E11C8 /* Defaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541A55046863031E15A9FA69EA99FE8E /* Defaultable.swift */; }; + 74339C58AC4E5631FB8C0E662668A796 /* UIApplication+StrictKeyWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 87C56FECBDEE19803E1748DE1C16FBBA /* UIApplication+StrictKeyWindow.m */; }; + 74B0953E6A82E0DDD4A50C6F3A64379B /* KeysMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0442ACE2BA5F7E00E86DA7955E7AF77 /* KeysMapper.swift */; }; + 75A9C102F3A707CD1C58A32620CB97FB /* PrintFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F9222551C78E09BFE29291610498A56 /* PrintFormat.swift */; }; + 78079FE3271F118CE83CFD8D5E4F8C21 /* TransformOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746BABF0910774EB502DC3C4F232413D /* TransformOf.swift */; }; + 78291B1F4027A71FC5DE0A74F491A68C /* JSONKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81A3A6F1AC972F8A54272A3F0CD7B26 /* JSONKeyedEncodingContainer.swift */; }; + 793D8DB41D7B4433B884003EA6A306D1 /* SmartAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAA37D00854B1424AE598ADE8E254D07 /* SmartAny.swift */; }; + 798C7D29511D498BDB7BEC4996708557 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CB9011E862E377A63B0CA2058DCEB78 /* Configuration.swift */; }; + 79C7D4E9901AA11C25F8C71F3E9DF612 /* Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0600D0B09DB5802D6B378850043ADD4D /* Properties.swift */; }; + 79FCA569BCE23251EE345047D3A15EFB /* BTBubble+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8396A1DCA6FC67A7830D34F6F815289 /* BTBubble+Draw.swift */; }; + 7A30E1AB144BAFBE0EBFB0A1FF40E6C0 /* SmartJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E9A27193AA9BC77F718F28EA0E1B65 /* SmartJSONDecoder.swift */; }; + 7AD2DE331157EFDE3B334048A5509E27 /* DecodingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D804957148656B5405037FC4821F4DB /* DecodingStrategy.swift */; }; + 7C67CBD15D9B5D0B7769B2F469478332 /* FBSnapshotTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = A11B531AF457EC4F99F06F115FDE0A45 /* FBSnapshotTestCase.m */; }; + 7D9031DCB898CD9DE37C4BD4F3FC550D /* DateFormatterTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F616A528D452098E003EDF888C54AC /* DateFormatterTransform.swift */; }; + 7E922AA455A7C6AFF9C4013D66AE30A8 /* JSONEncoderImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 995E5EF37D2EA75ADFF0B21D968E5B58 /* JSONEncoderImpl.swift */; }; + 846C97A8C420EFD9B8C4B77ADBB1E8F5 /* TransformType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20ABA9C7B9C59A9D3A5EA7AB0215871 /* TransformType.swift */; }; + 85913D5AC8449037C282EB84450592A1 /* CleanJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D3430E32742C8A84D354226C873C6C /* CleanJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 875A310EAF4D0C136C3FFFF5E0335BE4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DA24A38BA9EE106B59E3D4C8DD1CE0E /* UIKit.framework */; }; + 884DB7B8E20C199509BC5B9A17263113 /* BTBubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09645CD0AE835FD6F2CC1C70F2768E6 /* BTBubble.swift */; }; + 8AE19756F0126FE92AF625E36F3D70FE /* UIImage+Compare.h in Headers */ = {isa = PBXBuildFile; fileRef = 60E0A4F5EA0780653EDE0A8F48FE2B14 /* UIImage+Compare.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8B85D89911D50E1DEAF25D920B6F3C5F /* Pods-SmartCodable_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB62CDC1D9A84669428234D73C264AF /* Pods-SmartCodable_Example-dummy.m */; }; + 8C3394695CB4CCECD873D1384F4BA076 /* Export.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B376CE8FE7B39265B74DCF06C524D2 /* Export.swift */; }; + 8CD5DE204C3C5F6557878ADE2675A406 /* HelpingMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4749570A46F497B425767CB4569ADF9 /* HelpingMapper.swift */; }; + 8D72B695C7EF0186A0C0F1A18F944880 /* PropertyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DCC7F0112605A85E8861B6A4E92D154 /* PropertyInfo.swift */; }; + 8E181742809C6F03AE51D0F6E52E57DA /* BTPrint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68F996F21CE4381BFEAC8BDD8BC5E788 /* BTPrint.swift */; }; + 90087A9E35991CBA33825140C0A58757 /* CleanJSONKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DFBE39A8F2F3352B5AB28C6FFC990E7 /* CleanJSONKeyedDecodingContainer.swift */; }; + 90125B40656B551C64C1431AED5DB411 /* SmartColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E807ABEAA7D69B696DEF09C5E71FF4F5 /* SmartColor.swift */; }; + 9092C0B8C31F6B6F13433DD90C34D983 /* LogCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B7BCC990372646D3640A2DF459E49F3 /* LogCache.swift */; }; + 92CC91D4B6AF0B3E18068CCFBE36A3B7 /* BubbleTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E7A774098C77B700C918B4B303354 /* BubbleTools.swift */; }; + 95E194A3AABB5407231E898B6686F73E /* ConstraintMakerRelatable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6BD8F9EB57322C72A42B7031485790 /* ConstraintMakerRelatable+Extensions.swift */; }; + 96D8402B4AFC4AC7349F1B487D6EB08C /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2852BF0E7B62CAF6AB4E994FD9DFF2DF /* Transformable.swift */; }; + 98F570DA48370453D648BD526FDAAEAA /* LayoutConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FD964253D6C1E0040497B2CA5505E /* LayoutConstraintItem.swift */; }; + 998ED11AB27A87F186FEF60D94B647B9 /* JSONDecoderImpl+unwrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D179B728984FF882E8BF4096799056 /* JSONDecoderImpl+unwrap.swift */; }; + 9A6CCC7BCACBE8218126670E6B08EF9E /* BTPrint-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6226D5547537E7D1F86B312E2F57D4F0 /* BTPrint-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9B979585D04DE16A51C0D86CBC20F558 /* JSONSingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EF8CFAD648CDD728E621EF9F95D03A0 /* JSONSingleValueEncodingContainer.swift */; }; + 9C9548E8B4675954566202F7B87FF0E6 /* ConstraintConstantTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D588A73906F98B13FC731364A9247E2 /* ConstraintConstantTarget.swift */; }; + 9D3C5E2F56838937146191468A893244 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E658F388F01C72599CA75537950B6095 /* XCTest.framework */; }; + 9E02CFFEFE1BEC978B512286F03D31DA /* ConstraintInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C72CEDB9E9899CABE8976D237E6C74 /* ConstraintInsetTarget.swift */; }; + A03FDA8BC5741880B1EF11AFD248EF48 /* ConstraintOffsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFC3023119381C8AA8F1A4F4106F012A /* ConstraintOffsetTarget.swift */; }; + A0BCC2B78BCA27EFAE901B4406942557 /* BTBubble-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A77DB2179984C4C073E5FC6BDCD19B77 /* BTBubble-dummy.m */; }; + A0E5EC9E431A5BD01C4695BC6AE5DEDA /* ExtendCustomModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1287F892FF63395DDABB49A2F8C39A3B /* ExtendCustomModelType.swift */; }; + A2D6CC53EF61C755B77BBFF31B1F0E76 /* _CleanJSONDecoder+Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A247AF8B486EBFFB5B5CED8A27FD6D94 /* _CleanJSONDecoder+Decode.swift */; }; + A3E3AB7C765C21AE17B1E6EE6560040C /* SnapKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 96FC33890F5B9F948392563B47A573A0 /* SnapKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A5A8BF973BFE9C9304372A26C9F2E35B /* ConstraintMakerExtendable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCBDA27A176AE2D1C34BA797339DE8BB /* ConstraintMakerExtendable.swift */; }; + A5E849B00E179FB98F3A2CC91378245A /* DecodingError+CleanJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E5E84322D1072C445D51381EACDD7D /* DecodingError+CleanJSON.swift */; }; + A674A2F3F5F0304A6524F702EA301B42 /* NSDecimalNumberTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9C9CD93F7F692FE8121F7F78EE6DB8 /* NSDecimalNumberTransform.swift */; }; + A7E56F88A901663F5B7650BE98735031 /* SmartCaseDefaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C90D9D754077A7B4B1B5AC50059287 /* SmartCaseDefaultable.swift */; }; + AA75627FBC8A28CB9F9E26CDE0062EFE /* Pods-SmartCodable_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6021C11E2C3E5FCDE30179E13E0E6452 /* Pods-SmartCodable_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AEBDDE282F5DE157BB6A94E40747BA34 /* JSONUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7807886D9111CBFB4ACB76EBC0B3D39F /* JSONUnkeyedEncodingContainer.swift */; }; + B03B5579590D528CBA6D11FF638BC2AF /* Typealiases.swift in Sources */ = {isa = PBXBuildFile; fileRef = F324FE66E2BF9B4B5B507729C64FD069 /* Typealiases.swift */; }; + B0CEED2441DE3C86F63B0810A71B3C9B /* SafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1D73F882F8E812397C7CC5B0A6618CD /* SafeDictionary.swift */; }; + B3DBC0B0B13A1A1458147668D370E8E5 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4FA9C2F58756A6AFCF914B64DC8959B /* Transformer.swift */; }; + B43017FEC99D227D4CDD81DD2C27D9D9 /* ConstraintMakerPrioritizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EEAE2746CE46B4119A1EF4CB96853D4 /* ConstraintMakerPrioritizable.swift */; }; + B48B49F742B16DCAF2A095F3C5B5567D /* JSONDecoderImpl+UnkeyedContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 829E66367677D2B1D0128D6D228FD3A4 /* JSONDecoderImpl+UnkeyedContainer.swift */; }; + B52281F9F4340D4FC8ABB2FEB1FEC08E /* UIImage+Compare.m in Sources */ = {isa = PBXBuildFile; fileRef = C5688C4B8AAD0B0302EE6D8567AB0A03 /* UIImage+Compare.m */; }; + B752F7C4BECB65894B1F49421049CE5F /* ConstraintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE40591DCBDB38549AD0FC756F3D616 /* ConstraintView.swift */; }; + BD47CB74CD9B2B4D2D942C9B65748DFB /* SnapKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 89305DC7AA8CF17C4DFF5582FDC4E381 /* SnapKit-dummy.m */; }; + BD90F922C39E6EAEAD85EBD1F2363841 /* CodingKeysConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB55010FADC798A0E3768269292E5E /* CodingKeysConverter.swift */; }; + BE432D00488E08C853DC689BE24C54F4 /* HandyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 26D82883F952766DDE67EB5398B66E76 /* HandyJSON-dummy.m */; }; + C390C6005353FB986CB52F474CEF8588 /* FBSnapshotTestController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAD959505600831AE1B1760854D7178 /* FBSnapshotTestController.m */; }; + C586DC95274CF5AABAD935AF549A8FB6 /* BTBubble+Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4475151C4A7FB0660C3CDE88C6863EEF /* BTBubble+Location.swift */; }; + C920144CE195D2198DAE63F2D976AADB /* HandyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 91D961BD3D7E5A4FD5EFC37B4EF49FD4 /* HandyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9F76407497DF0205D7460B36D22259F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3280BB5E7B57C31D41117A74F76E9DF3 /* QuartzCore.framework */; }; + CA37B929250C9E1626AD815019BE9954 /* IgnoredKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037188BAD3B6E3D97703822C3762791B /* IgnoredKey.swift */; }; + CA54C09A12400567AFFCB407EEB7E154 /* UIImage+Diff.m in Sources */ = {isa = PBXBuildFile; fileRef = 209CC75BF3B9E4EF12E2CCE8787F9095 /* UIImage+Diff.m */; }; + CCCEE128C2F395CE7E3A13D343BC350B /* BTBubble+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C236F0CDFBBFF56E8E482E41A943E19E /* BTBubble+Animation.swift */; }; + CEDC7E5C39E615384342D437FD2309AC /* SmartJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1A452E1BB4D2E97E82928F4C874C8C1 /* SmartJSONEncoder.swift */; }; + CF7FAB0C5D474E379798F82E5DB4092B /* ContextDescriptorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796F5B9A676DF8041A953891F97BCA27 /* ContextDescriptorType.swift */; }; + D0C420537689BFE4829BDBC476CE326F /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36F08B193D052643664F581E6D09590 /* JSONParser.swift */; }; + D277ACC49DD7D3C3A660F4E834876790 /* Patcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA87DC4C55FBD71FD524E23BC5B638D4 /* Patcher.swift */; }; + D96D4E9317083E36E6CAA29795DAE10E /* EncodingCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F3DB64808585AF7EC48453CC5E40015 /* EncodingCache.swift */; }; + DE13D920EE02866495C19B6484C998DD /* BTBubbleConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 666C02C1B42B0868B4A816FBD07E22A6 /* BTBubbleConfig.swift */; }; + DF493E247E463CAC344C15784C9EF5AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */; }; + E2EF09A2D0A87418F0628B2CFAD304D8 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1BBC050B82F2DBD3175EBCDBBAE1B6 /* Metadata.swift */; }; + E7035A074129575E62A0136DD93D8E8F /* DateTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FD0E02013F60456068DC82258C06AB1 /* DateTransform.swift */; }; + E710A550162879CE918FC411CF567789 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0965E60C4A8A6CB4CDB3FD2D5BF45433 /* Logger.swift */; }; + E98DC8FB2578E76A812E0C94BA10E1B1 /* ConstraintDirectionalInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3803A342F79D0DBAEE0150E93A6B807B /* ConstraintDirectionalInsets.swift */; }; + ED71E932B7F30AD7CFD2A04968A2B5CC /* CBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 390DC8D2A8DB0DAB9CA70268C2F74AF4 /* CBridge.swift */; }; + EEFF0A57765CB734CF01868904F56DA7 /* HandyJSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D31C1D12C0D9C516CE738486208A159 /* HandyJSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EF21586EC3DFF6097A58EEC87376A0C1 /* ConstraintLayoutGuideDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1245F46A35053D954B8985EFAFD068D7 /* ConstraintLayoutGuideDSL.swift */; }; + F16D0BB1231D60CBF7B3AE25B92D0D74 /* EnumTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C30DC42DFE9E9BEB719E4821761599C5 /* EnumTransform.swift */; }; + F47FA5DC0D1BD01F21FEE05C02A165AD /* _CleanJSONDecoder+Unbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7BBDFD017622786401A39F6BD9686C8 /* _CleanJSONDecoder+Unbox.swift */; }; + F5B60A9B96EEF8DC4A1772856C6BC0B0 /* SmartCodable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9771EF69C497A5113339604D439DBD71 /* SmartCodable-dummy.m */; }; + F7425A58E24926CCAC413F85D403B9FA /* FieldDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ACD8767AB4E2B782160808FED94FADE /* FieldDescriptor.swift */; }; + F7C0960CEEB8F0C18F4503B405EAC08F /* ConstraintMultiplierTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551BC954C9673D937C2CA52B935158E1 /* ConstraintMultiplierTarget.swift */; }; + F953AA9104BFE0C2DAD639EA60104A75 /* ConstraintView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59BB800622705BC689D002AFE6C24643 /* ConstraintView+Extensions.swift */; }; + F98E3202B0021DC8B2DB77256FBE5DD3 /* ISO8601DateTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = C57A6E8C38153E40B8497C02204DF7F4 /* ISO8601DateTransform.swift */; }; + FAB03959C2357E325B19E08BC4775DAB /* ConstraintMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A4757260F219342EC59610827085045 /* ConstraintMaker.swift */; }; + FEFE2DDEB18C3D76F500C974F166CD53 /* CaseDefaultable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDE8674ED579EE94A0773028BD44AF1 /* CaseDefaultable.swift */; }; + FF8307B7346F4D3BA13C11AECFE6EDD0 /* FBSnapshotTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 20BC59163CF72AADA6459ADA846EBF1F /* FBSnapshotTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 0D80BECEC6D0C39E4473C712847963D6 /* PBXContainerItemProxy */ = { + 49357A36824C1AEBD1223BCD45855020 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 98A98149697C80CEF8D5772791E92E66; - remoteInfo = FBSnapshotTestCase; + remoteGlobalIDString = BD33823B9D08265B6F1D35EC259EE307; + remoteInfo = SmartCodable; }; - 149B2E93D51792ED0408223387C5CFFA /* PBXContainerItemProxy */ = { + 49E2F178442247BE29DEBD19074B517C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 19622742EBA51E823D6DAE3F8CDBFAD4; remoteInfo = SnapKit; }; - 1E1FAB8076135CEB813BD0C89B3B1BEC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CA298FF53B6D582AE40929DFE1454BBD; - remoteInfo = WCDB.swift; - }; - 291AF8D092EAF614778FB328CB5A01BB /* PBXContainerItemProxy */ = { + 6315A57DF9B64E5A259DD02D5ED0266F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = BD33823B9D08265B6F1D35EC259EE307; - remoteInfo = SmartCodable; + remoteGlobalIDString = 98A98149697C80CEF8D5772791E92E66; + remoteInfo = FBSnapshotTestCase; }; - 56662DD9F2DD6870F9050890F21FF036 /* PBXContainerItemProxy */ = { + 6E0BBD30A09157B277E47898D23EFCAC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 300904838EEDDC3BB8242817D8F97CB6; remoteInfo = CleanJSON; }; - 5B82222503485AC3C5895757582545D3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 46B68FB361B0E581CECCA815555333A6; - remoteInfo = SQLiteRepairKit; - }; - 78B4A1FF9CA093A6212FE27CF20C69A2 /* PBXContainerItemProxy */ = { + 94237F2B4B215E198D13C2E1DB5AF7CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 46B68FB361B0E581CECCA815555333A6; - remoteInfo = SQLiteRepairKit; - }; - 87CFBEC65473B9ED7865D5DE6D71B9FD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7AC2C6E1735146F1E0A04614976C5D18; - remoteInfo = WCDBOptimizedSQLCipher; + remoteGlobalIDString = 10D88C24864319FF583AD6D156896F32; + remoteInfo = HandyJSON; }; - 9C2578187BA172FE98132A3A214835D1 /* PBXContainerItemProxy */ = { + B48F0F8C314B97FBBE684F90D6D7E7B4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = B8474377209826CA7C2ADD548D40C1EA; remoteInfo = "Pods-SmartCodable_Example"; }; - A647F78DF0D8E6CB3697C24A542F283C /* PBXContainerItemProxy */ = { + D7C8282C3274F6325643139E95457EF5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 8ABBD9D5C40976C9B3FC1E227AAC109C; remoteInfo = BTBubble; }; - A89ABCA7FB4E81E34D7A14328380FDBA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7AC2C6E1735146F1E0A04614976C5D18; - remoteInfo = WCDBOptimizedSQLCipher; - }; - A959223D7063CF06C8F4F6AAB0E60F95 /* PBXContainerItemProxy */ = { + F3D2A2EA822A0F03E6C3B94C16A2BA60 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 86A81D2B2BFEFD93197A1D6C3C7EF60A; remoteInfo = BTPrint; }; - CD56A044224A6CD0300BAEEF44B16369 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 10D88C24864319FF583AD6D156896F32; - remoteInfo = HandyJSON; - }; - F24509FBD3F2F499D1BB6497135D42CE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7AC2C6E1735146F1E0A04614976C5D18; - remoteInfo = WCDBOptimizedSQLCipher; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 007BA55F5D4490BD94C8451E76A00455 /* Serializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Serializer.swift; path = Source/Serializer.swift; sourceTree = ""; }; - 00E1722C947F1DA1DF228499FC65654C /* CommonStatement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CommonStatement.swift; path = swift/source/builtin/CommonStatement.swift; sourceTree = ""; }; - 00FE0A814FC0CF97A87C4BF7AE3C52EE /* os_wcdb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = os_wcdb.h; path = src/os_wcdb.h; sourceTree = ""; }; - 0110482CEAC61185104B0F2A20BFB4B6 /* HandyJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HandyJSON-umbrella.h"; sourceTree = ""; }; - 0138F7570768B19CEE6F7AB7AE7D1841 /* pcache.c */ = {isa = PBXFileReference; includeInIndex = 1; name = pcache.c; path = src/pcache.c; sourceTree = ""; }; - 014B1C0CEA4BF05C07C0E27BA426D4DA /* opcodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = opcodes.h; sourceTree = ""; }; - 017E9F0474BFE7DA39821ABE5ED3C7D3 /* Typealiases.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Typealiases.swift; path = Sources/Typealiases.swift; sourceTree = ""; }; - 0269A1B2522AF958CF8C0F8F70F0621A /* CaseDefaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CaseDefaultable.swift; path = Sources/CleanJSON/CaseDefaultable.swift; sourceTree = ""; }; - 02F1F533ACB6C749844E6C51143FD7CC /* mem2.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mem2.c; path = src/mem2.c; sourceTree = ""; }; - 03BA22166A075933C743B2C9D1C85E9F /* SmartCodable.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SmartCodable.modulemap; sourceTree = ""; }; - 04943FF1F9F4BCCF3A02297282CCAF6E /* SmartJSONKeyedDecodingContainer+decodeIfPresent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SmartJSONKeyedDecodingContainer+decodeIfPresent.swift"; sourceTree = ""; }; - 04AF682E0F5A9200126922C904DB3A17 /* mem1.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mem1.c; path = src/mem1.c; sourceTree = ""; }; - 052C76D3ECB08C7CE97A583A8F4AA784 /* CodingTableKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CodingTableKey.swift; path = swift/source/core/codable/CodingTableKey.swift; sourceTree = ""; }; - 06654512231B9F787D6A5363A3BB410D /* crypto_cc.c */ = {isa = PBXFileReference; includeInIndex = 1; name = crypto_cc.c; path = src/crypto_cc.c; sourceTree = ""; }; - 06748A1A350AAD18055FC22AD20BBB46 /* upsert.c */ = {isa = PBXFileReference; includeInIndex = 1; name = upsert.c; path = src/upsert.c; sourceTree = ""; }; - 07024BD00FC36634A74C70568308AA01 /* ColumnResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnResult.swift; path = swift/source/abstract/ColumnResult.swift; sourceTree = ""; }; - 074E54E9F3324F34290CCDEE383AE984 /* Transformable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transformable.swift; path = Source/Transformable.swift; sourceTree = ""; }; - 080B01573DB252F29350F0BEB393D939 /* Column.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Column.swift; path = swift/source/abstract/Column.swift; sourceTree = ""; }; - 08951D687428D680F5A7D8AA9B6859F5 /* HelpingMapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpingMapper.swift; path = Source/HelpingMapper.swift; sourceTree = ""; }; - 08B65986CEFE01B5D27D34B5B6DC285E /* SmartCodable.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SmartCodable.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 0986BCD62FBDFF356818F2240DB86644 /* SQLiteRepairKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SQLiteRepairKit-dummy.m"; sourceTree = ""; }; - 0A67D02E48C372F7F65EF8E90E5E4446 /* CodableType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CodableType.swift; path = swift/source/builtin/CodableType.swift; sourceTree = ""; }; - 0AE978CDB4DB8CE29F1012CDCB29CDE7 /* Properties.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Properties.swift; path = Source/Properties.swift; sourceTree = ""; }; - 0B13703C34892E109DC262AD9E026413 /* fts3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fts3.h; path = ext/fts3/fts3.h; sourceTree = ""; }; - 0B4C445819691E20C66A3B0C876E8F09 /* Update.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Update.swift; path = swift/source/core/interface/Update.swift; sourceTree = ""; }; + 019BF859EEBE1D8469A3CE37606A8760 /* HandyJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HandyJSON.modulemap; sourceTree = ""; }; + 02A4470686F2D00D08E538160531B64E /* BTBubble+Menu.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Menu.swift"; path = "BTBubble/Classes/BTBubble+Menu.swift"; sourceTree = ""; }; + 02B734C740F66C4CA7D3E58A2E3A71ED /* UIImage+Snapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Snapshot.m"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.m"; sourceTree = ""; }; + 037188BAD3B6E3D97703822C3762791B /* IgnoredKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = IgnoredKey.swift; sourceTree = ""; }; + 05DE8DDCC94E79120DAB11B9DBD24069 /* ConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintItem.swift; path = Sources/ConstraintItem.swift; sourceTree = ""; }; + 0600D0B09DB5802D6B378850043ADD4D /* Properties.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Properties.swift; path = Source/Properties.swift; sourceTree = ""; }; + 077FF679DE0A788D695D32FCF72B1002 /* ConstraintConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConfig.swift; path = Sources/ConstraintConfig.swift; sourceTree = ""; }; + 07ADF3C4B3DE46FA90A67725C575E757 /* _CleanJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = _CleanJSONDecoder.swift; path = Sources/CleanJSON/_CleanJSONDecoder.swift; sourceTree = ""; }; + 0965E60C4A8A6CB4CDB3FD2D5BF45433 /* Logger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Logger.swift; path = Source/Logger.swift; sourceTree = ""; }; + 0B7BCC990372646D3640A2DF459E49F3 /* LogCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogCache.swift; sourceTree = ""; }; 0B9662B4BE2283F2E38F7155D5266F8E /* Pods-SmartCodable_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-SmartCodable_Tests"; path = Pods_SmartCodable_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0BB4D815AD7FDFA7FE61D12B8DBB2534 /* Tokenize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tokenize.swift; path = swift/source/abstract/Tokenize.swift; sourceTree = ""; }; - 0CCB1D63CBD4130578F32B453D318E7B /* VirtualTableBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VirtualTableBinding.swift; path = swift/source/core/binding/VirtualTableBinding.swift; sourceTree = ""; }; - 0D2C261220137389577E0E25D9696F66 /* rtree.c */ = {isa = PBXFileReference; includeInIndex = 1; name = rtree.c; path = ext/rtree/rtree.c; sourceTree = ""; }; - 0D452F86E76CB24DF6ECA35D83AA8248 /* trigger.c */ = {isa = PBXFileReference; includeInIndex = 1; name = trigger.c; path = src/trigger.c; sourceTree = ""; }; - 0D67E5BBBE0B0CE733CE89F049DA3E12 /* TimedQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TimedQueue.swift; path = swift/source/util/TimedQueue.swift; sourceTree = ""; }; - 0DDAA9762BFF90942F2F387B26557AA5 /* StatementCreateIndex.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementCreateIndex.swift; path = swift/source/abstract/StatementCreateIndex.swift; sourceTree = ""; }; - 0E157DD40B43D7133F4386E4833E41D3 /* pragma.c */ = {isa = PBXFileReference; includeInIndex = 1; name = pragma.c; path = src/pragma.c; sourceTree = ""; }; - 0E57B503B4EBCFD7AA0E51360A97AE18 /* ConstraintDirectionalInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsetTarget.swift; path = Sources/ConstraintDirectionalInsetTarget.swift; sourceTree = ""; }; - 0FDC79FFAFD807358086B52EA83BF2AB /* pcache1.c */ = {isa = PBXFileReference; includeInIndex = 1; name = pcache1.c; path = src/pcache1.c; sourceTree = ""; }; - 1187CAE253A8264680CBBC4D3BF3AE54 /* SmartJSONDecodingStorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartJSONDecodingStorage.swift; sourceTree = ""; }; - 11E4EA8972278437BFB8CED63ECCD00D /* Logger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Logger.swift; path = Source/Logger.swift; sourceTree = ""; }; - 11FBCD4D36359C93A5A40BC3BDEF2CD0 /* SmartJSONKeyedDecodingContainer+decode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SmartJSONKeyedDecodingContainer+decode.swift"; sourceTree = ""; }; - 14972CEEF09B3920E3ED07D20713219B /* ConstraintDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDSL.swift; path = Sources/ConstraintDSL.swift; sourceTree = ""; }; - 14C767AB16373063799E33054D23146A /* EnumTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EnumTransform.swift; path = Source/EnumTransform.swift; sourceTree = ""; }; - 14E440614E76DBC6A5930D8F20B2042D /* Pragma.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Pragma.swift; path = swift/source/abstract/Pragma.swift; sourceTree = ""; }; - 15335B1C99316156D53EFB132C72D90B /* EnumType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EnumType.swift; path = Source/EnumType.swift; sourceTree = ""; }; - 153C1F6555FA7C044BD0F0CC4C375069 /* fts3_unicode.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_unicode.c; path = ext/fts3/fts3_unicode.c; sourceTree = ""; }; - 15854FC71FC55631BB77E2D925160F40 /* select.c */ = {isa = PBXFileReference; includeInIndex = 1; name = select.c; path = src/select.c; sourceTree = ""; }; - 15AA5C0185FEA92FCCC59356558DB25B /* Core.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Core.swift; path = swift/source/core/base/Core.swift; sourceTree = ""; }; - 15CC97091BEEC9AAC898E58EC68EBF05 /* BTPrint-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTPrint-umbrella.h"; sourceTree = ""; }; - 16AD943F9AA80E1E0F94A0D7B760B5BA /* ConstraintInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsets.swift; path = Sources/ConstraintInsets.swift; sourceTree = ""; }; - 16FAB580F3341857A02C000870F30103 /* vdbe.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vdbe.h; path = src/vdbe.h; sourceTree = ""; }; - 1710B685152D86B0CBB66C7CFD397597 /* JoinClause.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JoinClause.swift; path = swift/source/abstract/JoinClause.swift; sourceTree = ""; }; - 186D22B5F301661D7D43BA272978F548 /* sqliterk_btree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_btree.h; path = repair/sqliterk_btree.h; sourceTree = ""; }; - 186F0AB785FEFD705F9810BF829E3B9F /* ConstraintMakerExtendable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerExtendable.swift; path = Sources/ConstraintMakerExtendable.swift; sourceTree = ""; }; - 189DDDBFF6D76C5E4E736A23810B2BFB /* Insert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Insert.swift; path = swift/source/core/interface/Insert.swift; sourceTree = ""; }; - 18D88FE24C75AD053966BC639186BD5D /* hash.c */ = {isa = PBXFileReference; includeInIndex = 1; name = hash.c; path = src/hash.c; sourceTree = ""; }; - 194C0EE64ACC9E3E4B7814090F7A7E53 /* Convertible.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Convertible.swift; path = swift/source/abstract/Convertible.swift; sourceTree = ""; }; - 1A8D1A79FED4B435F107DC9231BCFBF3 /* SQLite-Bridging.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SQLite-Bridging.swift"; path = "swift/source/util/SQLite-Bridging.swift"; sourceTree = ""; }; - 1A9F59771C2F07940C3D3E1D3219BEB2 /* StatementSavepoint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementSavepoint.swift; path = swift/source/abstract/StatementSavepoint.swift; sourceTree = ""; }; - 1AE97353C403B1B353D4887A7644E854 /* StatementRelease.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementRelease.swift; path = swift/source/abstract/StatementRelease.swift; sourceTree = ""; }; - 1C620067F708F6A1819086FB1A562860 /* UILayoutSupport+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UILayoutSupport+Extensions.swift"; path = "Sources/UILayoutSupport+Extensions.swift"; sourceTree = ""; }; - 1D0B07DBB6CE6B51956B3F9FCE907678 /* ConstraintMakerRelatable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintMakerRelatable+Extensions.swift"; path = "Sources/ConstraintMakerRelatable+Extensions.swift"; sourceTree = ""; }; - 1D697FCDF8A877E72AE4E548CE2110DE /* ctime.c */ = {isa = PBXFileReference; includeInIndex = 1; name = ctime.c; path = src/ctime.c; sourceTree = ""; }; - 1DF9DF1A9D97BEF7AF54F2FEFEE23AE0 /* SnapKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-umbrella.h"; sourceTree = ""; }; - 1E5130A0E082DB74881AC7C0818F8965 /* fkey.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fkey.c; path = src/fkey.c; sourceTree = ""; }; - 1E5911145B436332EF43EBBDE7E6CDA9 /* FBSnapshotTestCasePlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCasePlatform.h; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.h; sourceTree = ""; }; - 1EF0B53B69337F7F4AA44D3A9F9CDE37 /* complete.c */ = {isa = PBXFileReference; includeInIndex = 1; name = complete.c; path = src/complete.c; sourceTree = ""; }; - 1F395FD9DAAC93BBEFF0485E5984DA3B /* BTBubble-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BTBubble-Info.plist"; sourceTree = ""; }; - 1FE209EF17490B7AE639036689E60ACF /* DataTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DataTransformer.swift; sourceTree = ""; }; - 2083F64F2D96303B570E6175B352347C /* resolve.c */ = {isa = PBXFileReference; includeInIndex = 1; name = resolve.c; path = src/resolve.c; sourceTree = ""; }; - 208BD4FE2601BA95A308D031441A72C3 /* UIImage+Diff.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Diff.m"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.m"; sourceTree = ""; }; - 208CAEC6673B7C0C55E8A260CA2E9936 /* sqlcipher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqlcipher.h; path = src/sqlcipher.h; sourceTree = ""; }; - 20BCCD509CA9B3F4E19F0B89D1F0DA9E /* queue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = queue.h; path = src/queue.h; sourceTree = ""; }; - 20EFA042731FA1BB8CE1D3B3CA1DB012 /* fts3.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3.c; path = ext/fts3/fts3.c; sourceTree = ""; }; - 215B5A8E4B87860917054FA268224A4A /* ColumnIndex.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnIndex.swift; path = swift/source/abstract/ColumnIndex.swift; sourceTree = ""; }; - 22EEC6388F35D221D7E345FF0D771E29 /* DateTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateTransformer.swift; sourceTree = ""; }; - 234332AF7FFA3F89DF56548B0498751F /* Lock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lock.swift; path = swift/source/util/Lock.swift; sourceTree = ""; }; - 2369A4FD37B12F6C5C3AD86835E5DCD9 /* ColumnTypeDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnTypeDecoder.swift; path = swift/source/core/codable/ColumnTypeDecoder.swift; sourceTree = ""; }; - 242B3038A4DB16F77DDCEDDE83743BC5 /* LogContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogContainer.swift; sourceTree = ""; }; - 248FD8535E726D670FA271336DD6BD81 /* crypto_impl.c */ = {isa = PBXFileReference; includeInIndex = 1; name = crypto_impl.c; path = src/crypto_impl.c; sourceTree = ""; }; - 2640505E1669FA0E4615AB6C2A07EACF /* analyze.c */ = {isa = PBXFileReference; includeInIndex = 1; name = analyze.c; path = src/analyze.c; sourceTree = ""; }; - 26F087E6B19DA0211F8B01B1D81F844C /* sqliterk_values.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_values.c; path = repair/sqliterk_values.c; sourceTree = ""; }; - 27C5818B69BFD80E9CD7AB0525DF22C2 /* vdbemem.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbemem.c; path = src/vdbemem.c; sourceTree = ""; }; - 27E0C82161F76C3621B9957E27ECF4E4 /* window.c */ = {isa = PBXFileReference; includeInIndex = 1; name = window.c; path = src/window.c; sourceTree = ""; }; - 282C9EF12770BB707851C8092FA502B1 /* TableEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableEncoder.swift; path = swift/source/core/codable/TableEncoder.swift; sourceTree = ""; }; - 28F8F94803B65B561FBB046FCFCE4EA7 /* ConstraintLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuide.swift; path = Sources/ConstraintLayoutGuide.swift; sourceTree = ""; }; - 298E9370B4A805049548CB01C7F08CF6 /* CleanJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CleanJSON-dummy.m"; sourceTree = ""; }; - 2995ACAFEB77466B338AF49949E0F10C /* keywordhash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = keywordhash.h; sourceTree = ""; }; - 2ACC1B7946BEDD0237B5D92F1A9EF9F3 /* fts3_unicode2.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_unicode2.c; path = ext/fts3/fts3_unicode2.c; sourceTree = ""; }; - 2AD26611F62EC841B8AA65D6D377987B /* where.c */ = {isa = PBXFileReference; includeInIndex = 1; name = where.c; path = src/where.c; sourceTree = ""; }; - 2B17CFDDAB4B7441B376FCCB678C499F /* Transaction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transaction.swift; path = swift/source/core/base/Transaction.swift; sourceTree = ""; }; - 2B5009BA615F605E4770A0F999C8EAC7 /* SmartCodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartCodable.swift; sourceTree = ""; }; - 2BAF3FD2C70B49834F7EC00332581CE7 /* sqliteLimit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliteLimit.h; path = src/sqliteLimit.h; sourceTree = ""; }; - 2BD0F700A73E13AE67151D1323421415 /* mutex_unix.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mutex_unix.c; path = src/mutex_unix.c; sourceTree = ""; }; - 2C4935A7C5516AB70886A15F59CC104A /* Conflict.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Conflict.swift; path = swift/source/abstract/Conflict.swift; sourceTree = ""; }; - 2DDE2047CA2148A5644CFD3E9B61B0C7 /* SmartCodingKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartCodingKey.swift; sourceTree = ""; }; - 2E56852052AF5A2DCBC105963F8669A3 /* os.c */ = {isa = PBXFileReference; includeInIndex = 1; name = os.c; path = src/os.c; sourceTree = ""; }; - 2F05955F92891DDC9863B462D73A04E5 /* fts3_hash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fts3_hash.h; path = ext/fts3/fts3_hash.h; sourceTree = ""; }; - 2FACBD8B689AF9C3F28B0EE67CE6F169 /* backup.c */ = {isa = PBXFileReference; includeInIndex = 1; name = backup.c; path = src/backup.c; sourceTree = ""; }; - 30204FFE690A0B9592706A78093E1503 /* dbstat.c */ = {isa = PBXFileReference; includeInIndex = 1; name = dbstat.c; path = src/dbstat.c; sourceTree = ""; }; - 30725197DB5D704DA8C15608B3F3AC42 /* Measuable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Measuable.swift; path = Source/Measuable.swift; sourceTree = ""; }; - 30D613F035701597084E06D383FA66CB /* Subquery.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Subquery.swift; path = swift/source/abstract/Subquery.swift; sourceTree = ""; }; - 30F209D4AE80852F7B2A473B433E6231 /* SteadyClock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SteadyClock.swift; path = swift/source/util/SteadyClock.swift; sourceTree = ""; }; - 314EE032EFE20CD4E06F74092A6C187D /* FBSnapshotTestCase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-umbrella.h"; sourceTree = ""; }; - 3237B54E492CA6E8870521CDD3F613BD /* Patcher+Provider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Patcher+Provider.swift"; sourceTree = ""; }; - 325544FCE455196B6F391EE9FFEE5DD0 /* tokenize.c */ = {isa = PBXFileReference; includeInIndex = 1; name = tokenize.c; path = src/tokenize.c; sourceTree = ""; }; - 32588646583AF8336B91EA2A0FB6CD2A /* StatementUpdate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementUpdate.swift; path = swift/source/abstract/StatementUpdate.swift; sourceTree = ""; }; - 327DC9387C1368E032434452F72153B7 /* ConstraintPriorityTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriorityTarget.swift; path = Sources/ConstraintPriorityTarget.swift; sourceTree = ""; }; - 338B1D796753AF41826F3EC41206089D /* Convenience.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Convenience.swift; path = swift/source/util/Convenience.swift; sourceTree = ""; }; - 33A1FC38E885F6CAA0517719FCC0A1B7 /* parse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = parse.h; sourceTree = ""; }; - 343F3B1E09790572A6CAFAF95010B39C /* SnapKit-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapKit-Info.plist"; sourceTree = ""; }; - 345703E7CF3B18DFA38742BF2DAD0EB3 /* Patcher+Transformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Patcher+Transformer.swift"; sourceTree = ""; }; - 345CF363ECE5628BDA0E1001B5661B0F /* HexColorTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HexColorTransform.swift; path = Source/HexColorTransform.swift; sourceTree = ""; }; - 35874CD3E2284E8C73B3DF226CFAFE02 /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = swift/source/abstract/Expression.swift; sourceTree = ""; }; - 35E2F9F18CD38FADE9FBDBA79C2036A5 /* status.c */ = {isa = PBXFileReference; includeInIndex = 1; name = status.c; path = src/status.c; sourceTree = ""; }; - 36BB093C85AFBFBE00809739200019A5 /* vdbeaux.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbeaux.c; path = src/vdbeaux.c; sourceTree = ""; }; - 36E64B194309465F02BCBBB4DFC42F58 /* os_setup.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = os_setup.h; path = src/os_setup.h; sourceTree = ""; }; + 0EE11E0147F987FD843DF343F4BEF9C5 /* SnapKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.debug.xcconfig; sourceTree = ""; }; + 0F043A0A52D038042BE4B2E250F39C46 /* ConstraintLayoutSupportDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupportDSL.swift; path = Sources/ConstraintLayoutSupportDSL.swift; sourceTree = ""; }; + 0F3C77A10532266D4C2017D4C5657D22 /* UILayoutSupport+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UILayoutSupport+Extensions.swift"; path = "Sources/UILayoutSupport+Extensions.swift"; sourceTree = ""; }; + 0F6C61A3718CAD5B727FA89E9A50D662 /* CleanJSON.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CleanJSON.debug.xcconfig; sourceTree = ""; }; + 0FD0E02013F60456068DC82258C06AB1 /* DateTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DateTransform.swift; path = Source/DateTransform.swift; sourceTree = ""; }; + 1245F46A35053D954B8985EFAFD068D7 /* ConstraintLayoutGuideDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuideDSL.swift; path = Sources/ConstraintLayoutGuideDSL.swift; sourceTree = ""; }; + 1287F892FF63395DDABB49A2F8C39A3B /* ExtendCustomModelType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExtendCustomModelType.swift; path = Source/ExtendCustomModelType.swift; sourceTree = ""; }; + 12D66D4EBB5005BCB197AA15A08144D1 /* BTPrint.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTPrint.release.xcconfig; sourceTree = ""; }; + 1A2453FB81C81C62905E16C3FD41C15D /* JSONAdapter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSONAdapter.swift; path = Sources/CleanJSON/JSONAdapter.swift; sourceTree = ""; }; + 1ACD8767AB4E2B782160808FED94FADE /* FieldDescriptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FieldDescriptor.swift; path = Source/FieldDescriptor.swift; sourceTree = ""; }; + 1DA24A38BA9EE106B59E3D4C8DD1CE0E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 1EE51CB52688C6956C3806BE1352E6A1 /* BTPrint.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTPrint.debug.xcconfig; sourceTree = ""; }; + 209CC75BF3B9E4EF12E2CCE8787F9095 /* UIImage+Diff.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Diff.m"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.m"; sourceTree = ""; }; + 20BC59163CF72AADA6459ADA846EBF1F /* FBSnapshotTestCase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCase.h; path = FBSnapshotTestCase/FBSnapshotTestCase.h; sourceTree = ""; }; + 233DAEDE45A5CF0A47B6462C8C9F92B4 /* UIApplication+StrictKeyWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIApplication+StrictKeyWindow.h"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h"; sourceTree = ""; }; + 24562DC38CD0C27E5FCC2152077E3513 /* BTBubble-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTBubble-prefix.pch"; sourceTree = ""; }; + 2565E609AC51A4E4FCA81F2594C690F6 /* FBSnapshotTestCase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.debug.xcconfig; sourceTree = ""; }; + 25A597F47861F7BE3A2E02D5EC48740D /* FBSnapshotTestCase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FBSnapshotTestCase-Info.plist"; sourceTree = ""; }; + 26D82883F952766DDE67EB5398B66E76 /* HandyJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HandyJSON-dummy.m"; sourceTree = ""; }; + 274BB5419B8D40BD05519C560CFC077D /* BTBubble-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BTBubble-Info.plist"; sourceTree = ""; }; + 2852BF0E7B62CAF6AB4E994FD9DFF2DF /* Transformable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Transformable.swift; path = Source/Transformable.swift; sourceTree = ""; }; + 2B7CFF9C9E99F6CB429445432536C7C2 /* Cachable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Cachable.swift; sourceTree = ""; }; + 2C93FB183FE769D1FC0CB904D2C557D6 /* SmartCodable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SmartCodable-prefix.pch"; sourceTree = ""; }; + 2CAD959505600831AE1B1760854D7178 /* FBSnapshotTestController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestController.m; path = FBSnapshotTestCase/FBSnapshotTestController.m; sourceTree = ""; }; + 2D804957148656B5405037FC4821F4DB /* DecodingStrategy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DecodingStrategy.swift; path = Sources/CleanJSON/DecodingStrategy.swift; sourceTree = ""; }; + 2DBF99060B70E1B6830A780BA2524ADA /* ConstraintPriorityTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriorityTarget.swift; path = Sources/ConstraintPriorityTarget.swift; sourceTree = ""; }; + 2DCC7F0112605A85E8861B6A4E92D154 /* PropertyInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PropertyInfo.swift; path = Source/PropertyInfo.swift; sourceTree = ""; }; + 2E274A3EAC25DB6D5C25C3CBB604248B /* Deserializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Deserializer.swift; path = Source/Deserializer.swift; sourceTree = ""; }; + 2EBF008F9DBB55C9A18375B6B87D22A3 /* HandyJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HandyJSON-prefix.pch"; sourceTree = ""; }; + 30C72CEDB9E9899CABE8976D237E6C74 /* ConstraintInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsetTarget.swift; path = Sources/ConstraintInsetTarget.swift; sourceTree = ""; }; + 319CD0A8663A00A572B4418C10FE8894 /* BTBubble+Check.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Check.swift"; path = "BTBubble/Classes/BTBubble+Check.swift"; sourceTree = ""; }; + 3280BB5E7B57C31D41117A74F76E9DF3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 32B376CE8FE7B39265B74DCF06C524D2 /* Export.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Export.swift; path = Source/Export.swift; sourceTree = ""; }; + 32C90D9D754077A7B4B1B5AC50059287 /* SmartCaseDefaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartCaseDefaultable.swift; sourceTree = ""; }; 36EE49CE4B82B9346139D56A516D1DB0 /* Pods-SmartCodable_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SmartCodable_Tests.debug.xcconfig"; sourceTree = ""; }; - 370B85F293D8CDDA899A559DE09A8A3E /* SQLiteRepairKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SQLiteRepairKit.debug.xcconfig; sourceTree = ""; }; - 3726384DD45BD42064D3422F0CCB9D9F /* SQLiteRepairKit-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SQLiteRepairKit-Info.plist"; sourceTree = ""; }; - 37BE3C52BE9E38A8757F78EF0A1829CE /* StatementAlterTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementAlterTable.swift; path = swift/source/abstract/StatementAlterTable.swift; sourceTree = ""; }; - 39158D4DDE62D27C5D0AEEDEBE7271D1 /* CBridge.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CBridge.swift; path = Source/CBridge.swift; sourceTree = ""; }; - 39C04B27E6710C0E07FB4EEEA8231088 /* ConstraintLayoutGuide+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintLayoutGuide+Extensions.swift"; path = "Sources/ConstraintLayoutGuide+Extensions.swift"; sourceTree = ""; }; - 3A5736E278A439A4F84876664433AD19 /* malloc.c */ = {isa = PBXFileReference; includeInIndex = 1; name = malloc.c; path = src/malloc.c; sourceTree = ""; }; - 3A669A12B69A63E0BEF5B0382A3A729B /* WCDB.swift */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = WCDB.swift; path = WCDBSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3A7336366091CEA7AA3B99B1550BB520 /* SmartKeyDecodingStrategy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartKeyDecodingStrategy.swift; sourceTree = ""; }; - 3ABF6303B4915731785B890B96086080 /* CleanDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanDecoder.swift; path = Sources/CleanJSON/CleanDecoder.swift; sourceTree = ""; }; - 3BCF255A8D93A5832ECBCCFD5006F2EA /* FBSnapshotTestController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestController.m; path = FBSnapshotTestCase/FBSnapshotTestController.m; sourceTree = ""; }; - 3C4FA0CCF2A2DA9C40F7751A1FA54192 /* StatementDetach.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementDetach.swift; path = swift/source/abstract/StatementDetach.swift; sourceTree = ""; }; - 3C8C2472E4FE52411D856291FE3408D2 /* MultiSelect.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultiSelect.swift; path = swift/source/core/interface/MultiSelect.swift; sourceTree = ""; }; - 3D07A0B1D2259F30D4DB6EA5C979D6D8 /* InitialModelCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InitialModelCache.swift; sourceTree = ""; }; - 3D41F501030CAB0211BB226AD82F40E6 /* whereInt.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = whereInt.h; path = src/whereInt.h; sourceTree = ""; }; - 3D8462A4E4A62FFAA2EA934440DD042D /* FBSnapshotTestCasePlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCasePlatform.m; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.m; sourceTree = ""; }; - 3DA5B0BB29BEE655E198C29614913C2A /* auth.c */ = {isa = PBXFileReference; includeInIndex = 1; name = auth.c; path = src/auth.c; sourceTree = ""; }; + 36F93E9634821D816540140F7E1D6199 /* HexColorTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HexColorTransform.swift; path = Source/HexColorTransform.swift; sourceTree = ""; }; + 3803A342F79D0DBAEE0150E93A6B807B /* ConstraintDirectionalInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsets.swift; path = Sources/ConstraintDirectionalInsets.swift; sourceTree = ""; }; + 390DC8D2A8DB0DAB9CA70268C2F74AF4 /* CBridge.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CBridge.swift; path = Source/CBridge.swift; sourceTree = ""; }; + 39B2DBA2FFE481C74723D3D77C1C4151 /* CleanJSONUnkeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONUnkeyedDecodingContainer.swift; path = Sources/CleanJSON/CleanJSONUnkeyedDecodingContainer.swift; sourceTree = ""; }; + 3A10F19A7083CCBB70471917A1BD6C04 /* SnapKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapKit.modulemap; sourceTree = ""; }; + 3A5490ABF50B6719BC634405F60AB3E6 /* URLTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = URLTransformer.swift; sourceTree = ""; }; + 3B1648D17E6B6A33B54A7906BC560E10 /* ConstraintPriority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriority.swift; path = Sources/ConstraintPriority.swift; sourceTree = ""; }; + 3CE069FEDA7806D9F405C9CD00DEBC07 /* SmartCodable.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SmartCodable.modulemap; sourceTree = ""; }; 3E623AAE662B463FDDE8B268BDEA3E7B /* SmartCodable */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SmartCodable; path = SmartCodable.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3E966EA41E66C041E21596A3772AADB3 /* Handle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Handle.swift; path = swift/source/abstract/Handle.swift; sourceTree = ""; }; + 3E6F38F38A655D1D2F8385D4A13D03BD /* FBSnapshotTestCase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.release.xcconfig; sourceTree = ""; }; 3EF66D087C187059D6E79CD68D3907BC /* Pods-SmartCodable_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SmartCodable_Tests-acknowledgements.plist"; sourceTree = ""; }; - 3F0C0136BF06270C5D625F26FC0A7E81 /* WCDBOptimizedSQLCipher-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "WCDBOptimizedSQLCipher-Info.plist"; sourceTree = ""; }; - 3F14A4BF349F40CAAB558A775EABD9D1 /* fts3Int.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fts3Int.h; path = ext/fts3/fts3Int.h; sourceTree = ""; }; - 4003C2B584F6E186819D97CEB2E63F46 /* BTBubble+Location.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Location.swift"; path = "BTBubble/Classes/BTBubble+Location.swift"; sourceTree = ""; }; - 4032808F9DA898CCC05CA3A09966607E /* HandyJSON.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HandyJSON.debug.xcconfig; sourceTree = ""; }; - 40A09FC531CEBD255071D71F9AA1FD3C /* threads.c */ = {isa = PBXFileReference; includeInIndex = 1; name = threads.c; path = src/threads.c; sourceTree = ""; }; - 40AB6BB3402A8F58BEB7A3B4C06CB9C2 /* WCDB.swift-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WCDB.swift-prefix.pch"; sourceTree = ""; }; - 40AFCC5DF480085E54766074710BC33F /* insert.c */ = {isa = PBXFileReference; includeInIndex = 1; name = insert.c; path = src/insert.c; sourceTree = ""; }; - 40DE48CED81F4007A52E53CD61D79161 /* OtherExtension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OtherExtension.swift; path = Source/OtherExtension.swift; sourceTree = ""; }; - 43E555ABFE305E012A37237BC940803F /* sqliterk_crypto.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_crypto.h; path = repair/sqliterk_crypto.h; sourceTree = ""; }; + 418DA1AEA18C4A4A1E5D84FCB60DA427 /* Debugging.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Debugging.swift; path = Sources/Debugging.swift; sourceTree = ""; }; + 43E7CEB1D2A3A5C0DBB12BF8FC56CB8E /* LogItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogItem.swift; sourceTree = ""; }; 43FB1C7B536B80216B8B21E7440AEC8C /* Pods-SmartCodable_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-SmartCodable_Tests.modulemap"; sourceTree = ""; }; - 43FFE7610801F54DFCE0B7C42FE349DB /* RecyclableCore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RecyclableCore.swift; path = swift/source/core/base/RecyclableCore.swift; sourceTree = ""; }; - 4456F7D1572273D7A8579F5AC4D14E2B /* mem5.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mem5.c; path = src/mem5.c; sourceTree = ""; }; - 446B401C0DD4B21F9A9BF00840223ED9 /* fts3_snippet.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_snippet.c; path = ext/fts3/fts3_snippet.c; sourceTree = ""; }; + 4475151C4A7FB0660C3CDE88C6863EEF /* BTBubble+Location.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Location.swift"; path = "BTBubble/Classes/BTBubble+Location.swift"; sourceTree = ""; }; + 45DCF5151BEFE9D3018AFB99FE8F580F /* ConstraintInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsets.swift; path = Sources/ConstraintInsets.swift; sourceTree = ""; }; 464021711643A3159A0B5B78CCC0347A /* Pods-SmartCodable_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SmartCodable_Tests-acknowledgements.markdown"; sourceTree = ""; }; - 46611858B8325FB36AD0D5F498366D03 /* build.c */ = {isa = PBXFileReference; includeInIndex = 1; name = build.c; path = src/build.c; sourceTree = ""; }; - 468DF5A09D8D79ADC328CC7F75D956AF /* Property.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Property.swift; path = swift/source/core/binding/Property.swift; sourceTree = ""; }; - 46A766AE91E8CF4C4930E74AD1BF9210 /* SmartAny.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartAny.swift; sourceTree = ""; }; - 4711916E7B6BC9EDCEB84C83D65ABE93 /* HandyJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HandyJSON-dummy.m"; sourceTree = ""; }; - 472F55A319BA51293F698631D979AE4E /* BTBubble.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BTBubble.modulemap; sourceTree = ""; }; - 47AFB782E50452241E979C069CCE7C93 /* BTBubble+Animation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Animation.swift"; path = "BTBubble/Classes/BTBubble+Animation.swift"; sourceTree = ""; }; - 47CA9F565D77284A1A541E3C884B8D9D /* SQLiteRepairKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SQLiteRepairKit.release.xcconfig; sourceTree = ""; }; - 4841EAB23923FDF7466BD02E50A85A28 /* ConstraintRelatableTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelatableTarget.swift; path = Sources/ConstraintRelatableTarget.swift; sourceTree = ""; }; - 4886E29175151E6108F75868065ABBF4 /* vdbeblob.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbeblob.c; path = src/vdbeblob.c; sourceTree = ""; }; - 48E65E8527303A5A1758E602CBFD988D /* FundamentalValue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FundamentalValue.swift; path = swift/source/abstract/FundamentalValue.swift; sourceTree = ""; }; - 4A21FD23B7B9D638D2D6437D1FCEEB48 /* date.c */ = {isa = PBXFileReference; includeInIndex = 1; name = date.c; path = src/date.c; sourceTree = ""; }; - 4A63818CFAB3CDEB4D9CE9D9BABC4541 /* ConstraintMakerFinalizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerFinalizable.swift; path = Sources/ConstraintMakerFinalizable.swift; sourceTree = ""; }; - 4A64B6A3CDB35FD693AE7CC214BED1B7 /* utf.c */ = {isa = PBXFileReference; includeInIndex = 1; name = utf.c; path = src/utf.c; sourceTree = ""; }; - 4A66148DE9C1A94AD684B306C4A2F0C6 /* vdbetrace.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbetrace.c; path = src/vdbetrace.c; sourceTree = ""; }; - 4A957AEE9B28E0D13775629CCEB31E52 /* SnapKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.release.xcconfig; sourceTree = ""; }; + 464FF18D590547BE7F4826907AFFE76D /* ConstraintRelation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelation.swift; path = Sources/ConstraintRelation.swift; sourceTree = ""; }; + 46D532B60E5A862BAED6B9ED6A3A06F7 /* LayoutConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraint.swift; path = Sources/LayoutConstraint.swift; sourceTree = ""; }; + 4A29F6A0D45AF40A67824A0487C3A989 /* FBSnapshotTestController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestController.h; path = FBSnapshotTestCase/FBSnapshotTestController.h; sourceTree = ""; }; + 4A4DC161ED69D1B1A989E4A6912C7B9A /* SmartCodable.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SmartCodable.release.xcconfig; sourceTree = ""; }; + 4B3CBC4CFD3D5E9ABDC56DDC685EACE4 /* ConstraintMakerEditable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerEditable.swift; path = Sources/ConstraintMakerEditable.swift; sourceTree = ""; }; 4B882D619BB4F3DBCA3958CF51481D0F /* Pods-SmartCodable_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-SmartCodable_Example.modulemap"; sourceTree = ""; }; - 4C3A6680786E7AEEAEBF6ACBC7F46634 /* btmutex.c */ = {isa = PBXFileReference; includeInIndex = 1; name = btmutex.c; path = src/btmutex.c; sourceTree = ""; }; 4C4A4F11E0D54192FCD7E73E00FD2841 /* Pods-SmartCodable_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SmartCodable_Tests-frameworks.sh"; sourceTree = ""; }; - 4C6B2412CFDC619866F34C07873D2D08 /* NSDecimalNumberTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSDecimalNumberTransform.swift; path = Source/NSDecimalNumberTransform.swift; sourceTree = ""; }; - 4C7A0EFE15E507C964CE79BE8AC57D92 /* msvc.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = msvc.h; path = src/msvc.h; sourceTree = ""; }; - 4CA7F1846B98306446ECE67F2856D9BB /* BTPrint-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BTPrint-dummy.m"; sourceTree = ""; }; - 4CBB539F9E04B803B7BA7228A07C5BEC /* ConstraintDirectionalInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsets.swift; path = Sources/ConstraintDirectionalInsets.swift; sourceTree = ""; }; - 4CF668240903ACFCD31E3E022039B6E6 /* whereexpr.c */ = {isa = PBXFileReference; includeInIndex = 1; name = whereexpr.c; path = src/whereexpr.c; sourceTree = ""; }; - 4D9E45948CEF9BF9077D26412102B6F9 /* DecodingError+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "DecodingError+Extension.swift"; sourceTree = ""; }; - 4E81302FD66DAE30D32CDED9F8F953D9 /* _SmartJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = _SmartJSONDecoder.swift; sourceTree = ""; }; - 4EAA4EAE56C6CAB52B38138385B834F9 /* WCDB.swift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = WCDB.swift.debug.xcconfig; sourceTree = ""; }; - 4EB84981C58672F8E06A0D4AC94C3282 /* TableBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableBinding.swift; path = swift/source/core/binding/TableBinding.swift; sourceTree = ""; }; - 4F5FEADCF099B87D561589E2F744AE16 /* CleanJSONKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONKey.swift; path = Sources/CleanJSON/CleanJSONKey.swift; sourceTree = ""; }; - 4F652B64AD7EA719869A9BB4E4D5B39A /* TableInterface.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableInterface.swift; path = swift/source/core/interface/TableInterface.swift; sourceTree = ""; }; - 4F8809F9A3B10DEA6DCA3CC98E08D622 /* BTPrint.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BTPrint.modulemap; sourceTree = ""; }; - 50553FB57F080F1E987A3CD55DE922CB /* StatementInsert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementInsert.swift; path = swift/source/abstract/StatementInsert.swift; sourceTree = ""; }; - 5100DD0D061A6FC95142F30916FF35E1 /* sqliterk_pager.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_pager.c; path = repair/sqliterk_pager.c; sourceTree = ""; }; - 5198AB42A90C8765E2052D192FC434CD /* wherecode.c */ = {isa = PBXFileReference; includeInIndex = 1; name = wherecode.c; path = src/wherecode.c; sourceTree = ""; }; - 51A93FC1E25AF66C3E9C18D8296E36B9 /* fts5.c */ = {isa = PBXFileReference; includeInIndex = 1; path = fts5.c; sourceTree = ""; }; - 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 5283B716A76A18C9B408E0035F555B6B /* vdbe.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbe.c; path = src/vdbe.c; sourceTree = ""; }; - 53D77D9C85C14C7889D991953799A90D /* _SmartJSONDecoder+SingleValueDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "_SmartJSONDecoder+SingleValueDecodingContainer.swift"; sourceTree = ""; }; - 54221FFC83764C52FD659D644D6F1ED8 /* SmartJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartJSONDecoder.swift; sourceTree = ""; }; - 54CFEEBCF51169AF0B1F315D69C8D33F /* JSONAdapter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = JSONAdapter.swift; path = Sources/CleanJSON/JSONAdapter.swift; sourceTree = ""; }; - 55309A18A8E224B31E20FF7DA75F1AE7 /* FBSnapshotTestCase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.release.xcconfig; sourceTree = ""; }; - 561BF226C66CCB775EEEF0E42F3E87BA /* sqlite3rtree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqlite3rtree.h; path = ext/rtree/sqlite3rtree.h; sourceTree = ""; }; - 56F0CCA54FAF427CF38B01CBAAE7E03D /* SmartCaseDefaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartCaseDefaultable.swift; sourceTree = ""; }; - 57112FF9C13E952D32767DE7E52A6998 /* WCDBOptimizedSQLCipher.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = WCDBOptimizedSQLCipher.debug.xcconfig; sourceTree = ""; }; - 57205A5656AF71CC52D58B1C38172870 /* LogCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogCache.swift; sourceTree = ""; }; - 57420310DABA9A536A9A0996B4DFFD11 /* StatementReindex.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementReindex.swift; path = swift/source/abstract/StatementReindex.swift; sourceTree = ""; }; - 5750120103B02747856DF9A69B4BCC83 /* mutex.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mutex.c; path = src/mutex.c; sourceTree = ""; }; - 5798E3AE0C35A0234890311B4DDB6BAA /* WCDBOptimizedSQLCipher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WCDBOptimizedSQLCipher-prefix.pch"; sourceTree = ""; }; - 57D9A0F7AD288FBCB187DF9CCC042E97 /* ExtendCustomBasicType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExtendCustomBasicType.swift; path = Source/ExtendCustomBasicType.swift; sourceTree = ""; }; - 586CEF3C778B1CA10216855665336254 /* SnapKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapKit.modulemap; sourceTree = ""; }; - 589169F9BA6B76B8D7A16765B1135F63 /* WCDB-Bridging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "WCDB-Bridging.h"; path = "swift/source/util/WCDB-Bridging.h"; sourceTree = ""; }; - 58EA21B6E71EBB420FCB0D177FFC3B0A /* opcodes.c */ = {isa = PBXFileReference; includeInIndex = 1; path = opcodes.c; sourceTree = ""; }; - 593175FB6C4DDBC7DBC7DAE352763FC2 /* WCDB.swift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WCDB.swift-umbrella.h"; sourceTree = ""; }; - 59E469590BC9F29B51275D3ED6913071 /* table.c */ = {isa = PBXFileReference; includeInIndex = 1; name = table.c; path = src/table.c; sourceTree = ""; }; - 59FD30BFD517239EAEF40A0E82542733 /* ModelKeyMapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ModelKeyMapper.swift; sourceTree = ""; }; - 5B1200BCAF314037FF573D41166091D8 /* SmartCodable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SmartCodable-umbrella.h"; sourceTree = ""; }; - 5B9BEE2C0EC151B67961F46092A989DE /* sqliterk.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk.h; path = repair/sqliterk.h; sourceTree = ""; }; - 5BEE5FD64126C65AE637CAF7B4E236D6 /* Export.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Export.swift; path = Source/Export.swift; sourceTree = ""; }; + 4C9DA5A2D5BD3067E4B62F006F3BCE6B /* SmartLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartLog.swift; sourceTree = ""; }; + 4CAE8816531C7030F85857D829CF295C /* BTBubble-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTBubble-umbrella.h"; sourceTree = ""; }; + 4FD9F7D2497A25B05DF82AF7F12F84DF /* BTBubble.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTBubble.debug.xcconfig; sourceTree = ""; }; + 510325960A63C34B69B7173F76A69109 /* URLTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLTransform.swift; path = Source/URLTransform.swift; sourceTree = ""; }; + 537BE90B32A5F1814137F702A3A820F6 /* HandyJSON.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HandyJSON.debug.xcconfig; sourceTree = ""; }; + 541A55046863031E15A9FA69EA99FE8E /* Defaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Defaultable.swift; path = Sources/CleanJSON/Defaultable.swift; sourceTree = ""; }; + 544353E196F6C41D2674EF54DDCED631 /* ConstraintLayoutSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupport.swift; path = Sources/ConstraintLayoutSupport.swift; sourceTree = ""; }; + 54E6DE8DDA000868195FED827A109AD1 /* BTPrint-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTPrint-prefix.pch"; sourceTree = ""; }; + 55017ACE8DE4C20B38E0C7802356E9C6 /* SmartCodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartCodable.swift; sourceTree = ""; }; + 551BC954C9673D937C2CA52B935158E1 /* ConstraintMultiplierTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMultiplierTarget.swift; path = Sources/ConstraintMultiplierTarget.swift; sourceTree = ""; }; + 555C1F46B8C3D9749B4FADF32ED4458D /* CleanJSONKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONKey.swift; path = Sources/CleanJSON/CleanJSONKey.swift; sourceTree = ""; }; + 56F3BDAC789DF61F2D9350035669FEE3 /* CleanJSON-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CleanJSON-Info.plist"; sourceTree = ""; }; + 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 57E62D2D77DEED3B201DFDA0618E0E9D /* LogContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogContainer.swift; sourceTree = ""; }; + 59BB800622705BC689D002AFE6C24643 /* ConstraintView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintView+Extensions.swift"; path = "Sources/ConstraintView+Extensions.swift"; sourceTree = ""; }; 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FBSnapshotTestCase; path = FBSnapshotTestCase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5CA8D934CA4195CBB60E7B64B4F6938D /* StatementCreateVirtualTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementCreateVirtualTable.swift; path = swift/source/abstract/StatementCreateVirtualTable.swift; sourceTree = ""; }; 5D1C54C47A2FE062765D133366160F7F /* Pods-SmartCodable_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SmartCodable_Example-acknowledgements.plist"; sourceTree = ""; }; - 5D6F6281A81E9332BA17E1E5D6E7AE6D /* BTBubble.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTBubble.release.xcconfig; sourceTree = ""; }; - 5DCCF5B5F792D4EC76585F50AC7D8D7B /* SQLiteRepairKit */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SQLiteRepairKit; path = sqliterk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5DAD6DAD58F97DC6978669ECC1DCB217 /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+SingleValueDecodingContainer.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+SingleValueDecodingContainer.swift"; sourceTree = ""; }; + 5EE456287EB50E4B04F1A29EC19043B7 /* ConstraintLayoutGuide+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintLayoutGuide+Extensions.swift"; path = "Sources/ConstraintLayoutGuide+Extensions.swift"; sourceTree = ""; }; 6021C11E2C3E5FCDE30179E13E0E6452 /* Pods-SmartCodable_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SmartCodable_Example-umbrella.h"; sourceTree = ""; }; - 60954761F92EED9592A31A783EC3B05E /* TableConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableConstraint.swift; path = swift/source/abstract/TableConstraint.swift; sourceTree = ""; }; - 60AD687D99290D39682062FBAB4B9530 /* ConstraintPriority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriority.swift; path = Sources/ConstraintPriority.swift; sourceTree = ""; }; - 611CDA25837467E463F32A67A9EF9FF6 /* mem0.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mem0.c; path = src/mem0.c; sourceTree = ""; }; + 60B0F726C42000735EC1B76226554746 /* UIImage+Snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Snapshot.h"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.h"; sourceTree = ""; }; + 60E0A4F5EA0780653EDE0A8F48FE2B14 /* UIImage+Compare.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Compare.h"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.h"; sourceTree = ""; }; 6170F13C22D7194151A678E232C31D12 /* Pods-SmartCodable_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SmartCodable_Example.release.xcconfig"; sourceTree = ""; }; - 63165FEB321973E0AD39AFA539EBD85F /* DecodingStrategy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DecodingStrategy.swift; path = Sources/CleanJSON/DecodingStrategy.swift; sourceTree = ""; }; + 61B5EAF366B8557B8062A765F73500C2 /* JSONFuture.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONFuture.swift; sourceTree = ""; }; + 6226D5547537E7D1F86B312E2F57D4F0 /* BTPrint-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTPrint-umbrella.h"; sourceTree = ""; }; + 63337F29437FD6A05DCA6E50C4DF6945 /* ExtendCustomBasicType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExtendCustomBasicType.swift; path = Source/ExtendCustomBasicType.swift; sourceTree = ""; }; 63D6FCCD448B91FE5083D3C830B09E34 /* BTPrint */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = BTPrint; path = BTPrint.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 6413BD32DD33B3C006539834A6029F46 /* SwiftSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftSupport.swift; path = FBSnapshotTestCase/SwiftSupport.swift; sourceTree = ""; }; - 644177FA36D4B8A4E563D29BDA08DFA1 /* Recyclable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Recyclable.swift; path = swift/source/util/Recyclable.swift; sourceTree = ""; }; - 65031BFCAFB9694B1F3F528750789158 /* sqliterk_btree.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_btree.c; path = repair/sqliterk_btree.c; sourceTree = ""; }; - 65425402E91EFABF55F0BF3523CE117D /* CleanJSON.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CleanJSON.debug.xcconfig; sourceTree = ""; }; - 65BEC92F44B8431C10E16C69DE91C591 /* CoreStatement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CoreStatement.swift; path = swift/source/core/base/CoreStatement.swift; sourceTree = ""; }; - 6655E8C804740DB2886BEC041DF12E7C /* UIImage+Compare.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Compare.m"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.m"; sourceTree = ""; }; - 665EF7716439F0B62542010899E7BC02 /* vdbeInt.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vdbeInt.h; path = src/vdbeInt.h; sourceTree = ""; }; - 672B415C1B19E7C0F422085F2399E7F0 /* SmartCodable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SmartCodable-prefix.pch"; sourceTree = ""; }; - 67862AEB121CDDE6370187F66B07A7EF /* bitvec.c */ = {isa = PBXFileReference; includeInIndex = 1; name = bitvec.c; path = src/bitvec.c; sourceTree = ""; }; - 6828855C8EB1DC703DFC765E3C8E9A27 /* fts5.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = fts5.h; sourceTree = ""; }; - 6866EE8AA2F1FF8308B5C3410AEA8C40 /* SQLiteRepairKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = SQLiteRepairKit.h; path = repair/SQLiteRepairKit.h; sourceTree = ""; }; - 686713A2ADF7635E962053D7B5BCDE83 /* HandyJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HandyJSON.modulemap; sourceTree = ""; }; - 6900708CD940876C68B468F9E43E35B5 /* ColumnDef.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnDef.swift; path = swift/source/abstract/ColumnDef.swift; sourceTree = ""; }; - 69EED8E214F52686EF00631CE13D11DA /* File.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = File.swift; path = swift/source/util/File.swift; sourceTree = ""; }; - 6A19D339940591628408D7B9957A84CF /* sqlite3ext.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqlite3ext.h; path = src/sqlite3ext.h; sourceTree = ""; }; - 6A335F1EDB942166F2779121CE29E585 /* os_wcdb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = os_wcdb.c; path = src/os_wcdb.c; sourceTree = ""; }; - 6B72E0611C67C73EA6510B95978F87CB /* BTBubble-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTBubble-prefix.pch"; sourceTree = ""; }; - 6BCD89A8AF7896E1C2C1B554E7A51E56 /* BTBubble.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTBubble.swift; path = BTBubble/Classes/BTBubble.swift; sourceTree = ""; }; - 6BF26EB92D747312A7EFF6EB2BE276AC /* StatementDropTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementDropTable.swift; path = swift/source/abstract/StatementDropTable.swift; sourceTree = ""; }; - 6CE9165B4A6C85359A6DCFB5752AF15C /* StatementCreateTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementCreateTable.swift; path = swift/source/abstract/StatementCreateTable.swift; sourceTree = ""; }; - 6D070A8985C735AB5F1CA1940115E588 /* hwtime.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = hwtime.h; path = src/hwtime.h; sourceTree = ""; }; - 6D0D80684CB2A17DDA87A11515761E6D /* rtree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = rtree.h; path = ext/rtree/rtree.h; sourceTree = ""; }; - 6D22BA786978818F4FE3FDB91C56F4A1 /* ConstraintLayoutSupportDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupportDSL.swift; path = Sources/ConstraintLayoutSupportDSL.swift; sourceTree = ""; }; - 6D4268C0E94A4D1CEA5A9AFA2C42E291 /* Metadata.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Metadata.swift; path = Source/Metadata.swift; sourceTree = ""; }; - 6DC7F8D1A909AADFB0E22BC9B1D3C7B4 /* SmartCodable-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SmartCodable-Info.plist"; sourceTree = ""; }; - 6DCAC454A3B4DC896C97A76C0162F55F /* sqliterk_os.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_os.h; path = repair/sqliterk_os.h; sourceTree = ""; }; - 6E36C3087AA75ECBCF695349CB5A749B /* BTPrint-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BTPrint-Info.plist"; sourceTree = ""; }; - 6EB49BA14169665C8D4821A83FD6E489 /* FBSnapshotTestCase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FBSnapshotTestCase-Info.plist"; sourceTree = ""; }; - 6FAA1DBD66A24E9AC890DC3D6119D2ED /* wal.c */ = {isa = PBXFileReference; includeInIndex = 1; name = wal.c; path = src/wal.c; sourceTree = ""; }; - 6FFB72C4FC2D499DF9218B70627E31C1 /* crypto_libtomcrypt.c */ = {isa = PBXFileReference; includeInIndex = 1; name = crypto_libtomcrypt.c; path = src/crypto_libtomcrypt.c; sourceTree = ""; }; - 7009D451088814BE5B398BCC801037CB /* HandyJSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HandyJSON.h; path = Source/HandyJSON.h; sourceTree = ""; }; - 7095CF12D4A8623FA91F06BD720560B8 /* parse.c */ = {isa = PBXFileReference; includeInIndex = 1; path = parse.c; sourceTree = ""; }; - 70B952A2FD0BD10A80C59B2F4BE7F89C /* SmartDecodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartDecodable.swift; sourceTree = ""; }; - 70EB956D11844218C49F91382D5686BB /* ConstraintLayoutGuideDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuideDSL.swift; path = Sources/ConstraintLayoutGuideDSL.swift; sourceTree = ""; }; + 64E44B798553A3E18727230F8D89E3F9 /* SmartEncodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartEncodable.swift; sourceTree = ""; }; + 666C02C1B42B0868B4A816FBD07E22A6 /* BTBubbleConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTBubbleConfig.swift; path = BTBubble/Classes/BTBubbleConfig.swift; sourceTree = ""; }; + 68F996F21CE4381BFEAC8BDD8BC5E788 /* BTPrint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTPrint.swift; path = BTPrint/Classes/BTPrint.swift; sourceTree = ""; }; + 6B6AE0B9AEB52789C2BA9C70151E337A /* MangledName.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MangledName.swift; path = Source/MangledName.swift; sourceTree = ""; }; + 6BAACBE9FC72DF06355302EE7B3A730E /* SmartUpdater.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartUpdater.swift; sourceTree = ""; }; + 6CDB55010FADC798A0E3768269292E5E /* CodingKeysConverter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CodingKeysConverter.swift; path = Sources/CleanJSON/CodingKeysConverter.swift; sourceTree = ""; }; + 6CF935F6F0BF80B0C79325C2A66921C8 /* HandyJSON.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HandyJSON.release.xcconfig; sourceTree = ""; }; + 6DFBE39A8F2F3352B5AB28C6FFC990E7 /* CleanJSONKeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONKeyedDecodingContainer.swift; path = Sources/CleanJSON/CleanJSONKeyedDecodingContainer.swift; sourceTree = ""; }; + 6FD01EC1237ED966BE6C99E868971093 /* Serializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Serializer.swift; path = Source/Serializer.swift; sourceTree = ""; }; + 70E88BDB3FDACE8F2B23F3247435107D /* ConstraintLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuide.swift; path = Sources/ConstraintLayoutGuide.swift; sourceTree = ""; }; 70EF9FF8800B0AA22F5E4FE76FECA8D7 /* Pods-SmartCodable_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SmartCodable_Example-Info.plist"; sourceTree = ""; }; - 712F259C7D5BEFCEDDBE627A309BD417 /* README-EN.md */ = {isa = PBXFileReference; includeInIndex = 1; path = "README-EN.md"; sourceTree = ""; }; - 72E993CD880CBB3208C2A588FB128358 /* printf.c */ = {isa = PBXFileReference; includeInIndex = 1; name = printf.c; path = src/printf.c; sourceTree = ""; }; - 73713A6806AC55107EA83D93F777C0A5 /* fts3_porter.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_porter.c; path = ext/fts3/fts3_porter.c; sourceTree = ""; }; - 73B5134C3B0D0DCBF20DA94AC4C405B7 /* mutex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mutex.h; path = src/mutex.h; sourceTree = ""; }; - 748AE91ABED537A2DF9E1BD4D1BD1216 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; - 74D8B544917AB1825600223F1847F8ED /* ConstraintConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConfig.swift; path = Sources/ConstraintConfig.swift; sourceTree = ""; }; - 75DD762DA8418DC60C817DD56DC3E353 /* WCDBTokenize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = WCDBTokenize.swift; path = swift/source/core/fts/WCDBTokenize.swift; sourceTree = ""; }; + 746BABF0910774EB502DC3C4F232413D /* TransformOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TransformOf.swift; path = Source/TransformOf.swift; sourceTree = ""; }; + 7570803E9622B6523B3325B01B79E44B /* ConstraintDescription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDescription.swift; path = Sources/ConstraintDescription.swift; sourceTree = ""; }; 767825513CDDC33C98AB0A7A3C9681D4 /* Pods-SmartCodable_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SmartCodable_Example-frameworks.sh"; sourceTree = ""; }; - 7730B02FC8DBB419EF7E5DD4C7069878 /* Interface.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Interface.swift; path = swift/source/core/interface/Interface.swift; sourceTree = ""; }; - 782FEEC464789BBF3AB2DEDD778C2B0A /* PropertyInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PropertyInfo.swift; path = Source/PropertyInfo.swift; sourceTree = ""; }; - 7867ADA3ACBECE3FE0964EB6C2ADF7D6 /* pcache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = pcache.h; path = src/pcache.h; sourceTree = ""; }; - 78CD18F607C4C7B3260A2086E6FA71F5 /* ConcurrentList.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConcurrentList.swift; path = swift/source/util/ConcurrentList.swift; sourceTree = ""; }; - 79255177DD8C05F8B7066A72ADC29525 /* update.c */ = {isa = PBXFileReference; includeInIndex = 1; name = update.c; path = src/update.c; sourceTree = ""; }; - 798614252B284BD86026E6391A1D6B83 /* HandleStatement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HandleStatement.swift; path = swift/source/abstract/HandleStatement.swift; sourceTree = ""; }; - 7B318245EAB932A9788ED4E4D8564AD0 /* Config.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Config.swift; path = swift/source/core/base/Config.swift; sourceTree = ""; }; - 7B59B3059BFCFF25377D0910E7F11C89 /* alter.c */ = {isa = PBXFileReference; includeInIndex = 1; name = alter.c; path = src/alter.c; sourceTree = ""; }; - 7B7110CEA112EBF2FC498D5380951730 /* SQLite-Bridging.c */ = {isa = PBXFileReference; includeInIndex = 1; name = "SQLite-Bridging.c"; path = "swift/source/util/SQLite-Bridging.c"; sourceTree = ""; }; - 7C5723CCC9FB17ECAE18AE1F0A10DC5C /* BTPrint.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTPrint.release.xcconfig; sourceTree = ""; }; - 7D02FC03949EB55EFDEB6BD91B376C88 /* Redirectable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Redirectable.swift; path = swift/source/core/binding/Redirectable.swift; sourceTree = ""; }; - 7D0587A335645BB79F0222497FF85E14 /* SQLite-Bridging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "SQLite-Bridging.h"; path = "swift/source/util/SQLite-Bridging.h"; sourceTree = ""; }; - 7D90EB55E616E8CECBE8918EF6E09491 /* StatementSelect.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementSelect.swift; path = swift/source/abstract/StatementSelect.swift; sourceTree = ""; }; - 7D936226781B9F30DC482374790455EF /* Table.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Table.swift; path = swift/source/core/interface/Table.swift; sourceTree = ""; }; - 7F3BEEE19C0A78E1A2CA95A33072BA36 /* Atomic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Atomic.swift; path = swift/source/util/Atomic.swift; sourceTree = ""; }; - 7FBD193AEDCC1BC474026921C4493237 /* StatementDropIndex.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementDropIndex.swift; path = swift/source/abstract/StatementDropIndex.swift; sourceTree = ""; }; - 8073B9C0CAD4D26D09EB8F8C618A816F /* ThreadLocal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThreadLocal.swift; path = swift/source/util/ThreadLocal.swift; sourceTree = ""; }; - 8153927F031D060140C06D57CFC4A431 /* SmartSONUnkeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartSONUnkeyedDecodingContainer.swift; sourceTree = ""; }; - 815ECC31D5B46D1C6B8D579980A78AC2 /* CodingKeysConverter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CodingKeysConverter.swift; path = Sources/CleanJSON/CodingKeysConverter.swift; sourceTree = ""; }; - 81A6B148540C158469908690D628A9BF /* pager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = pager.h; path = src/pager.h; sourceTree = ""; }; - 81DB024EC9AFF73AA4502F4734CA810C /* delete.c */ = {isa = PBXFileReference; includeInIndex = 1; name = delete.c; path = src/delete.c; sourceTree = ""; }; - 820888330A2D426AAA53548B20928AC6 /* fts3_icu.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_icu.c; path = ext/fts3/fts3_icu.c; sourceTree = ""; }; - 8224719BF93802AC51382B196A6B30C5 /* IgnoredKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = IgnoredKey.swift; sourceTree = ""; }; - 82C013A66AAE87D26F22C959065F6D3B /* sqlite3rbu.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqlite3rbu.h; path = ext/rbu/sqlite3rbu.h; sourceTree = ""; }; - 837D4D1D0F21909CC79D931A54D8C932 /* CleanJSONUnkeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONUnkeyedDecodingContainer.swift; path = Sources/CleanJSON/CleanJSONUnkeyedDecodingContainer.swift; sourceTree = ""; }; - 83F45E6394093E1369C044D428C8879A /* Order.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Order.swift; path = swift/source/abstract/Order.swift; sourceTree = ""; }; - 848CD67E6D3721BE0AB072D0731ED981 /* BubbleTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleTools.swift; path = BTBubble/Classes/BubbleTools.swift; sourceTree = ""; }; - 84F8D67CFB1FB3199FB53CCFDA73794D /* RWLock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RWLock.swift; path = swift/source/util/RWLock.swift; sourceTree = ""; }; + 76F616A528D452098E003EDF888C54AC /* DateFormatterTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DateFormatterTransform.swift; path = Source/DateFormatterTransform.swift; sourceTree = ""; }; + 7807886D9111CBFB4ACB76EBC0B3D39F /* JSONUnkeyedEncodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONUnkeyedEncodingContainer.swift; sourceTree = ""; }; + 796F5B9A676DF8041A953891F97BCA27 /* ContextDescriptorType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextDescriptorType.swift; path = Source/ContextDescriptorType.swift; sourceTree = ""; }; + 7AA1897EAAC2C936DF3C2195D9388328 /* JSONValue+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "JSONValue+Extension.swift"; sourceTree = ""; }; + 7CB9011E862E377A63B0CA2058DCEB78 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Source/Configuration.swift; sourceTree = ""; }; + 7D0C0E237F70C307DF23B940F50265F5 /* Measuable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Measuable.swift; path = Source/Measuable.swift; sourceTree = ""; }; + 7D588A73906F98B13FC731364A9247E2 /* ConstraintConstantTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConstantTarget.swift; path = Sources/ConstraintConstantTarget.swift; sourceTree = ""; }; + 7E920302DBA2124AFF869243E5CB6351 /* BuiltInBridgeType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BuiltInBridgeType.swift; path = Source/BuiltInBridgeType.swift; sourceTree = ""; }; + 7EEAE2746CE46B4119A1EF4CB96853D4 /* ConstraintMakerPrioritizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerPrioritizable.swift; path = Sources/ConstraintMakerPrioritizable.swift; sourceTree = ""; }; + 7F1BBC050B82F2DBD3175EBCDBBAE1B6 /* Metadata.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Metadata.swift; path = Source/Metadata.swift; sourceTree = ""; }; + 7F9222551C78E09BFE29291610498A56 /* PrintFormat.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PrintFormat.swift; path = BTPrint/Classes/PrintFormat.swift; sourceTree = ""; }; + 7FF03B8E2DF800F666228FD3C0F9026B /* FBSnapshotTestCase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-umbrella.h"; sourceTree = ""; }; + 7FFEEBFE7C3F6CA97EC2C91D3BF3AA9B /* DecodingCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DecodingCache.swift; sourceTree = ""; }; + 829E66367677D2B1D0128D6D228FD3A4 /* JSONDecoderImpl+UnkeyedContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "JSONDecoderImpl+UnkeyedContainer.swift"; sourceTree = ""; }; 85D2CD4F67092C56E310282E114ADE5B /* Pods-SmartCodable_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SmartCodable_Example-acknowledgements.markdown"; sourceTree = ""; }; - 85D8102D03B9C841FD3EC7FC419350D7 /* Defaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Defaultable.swift; path = Sources/CleanJSON/Defaultable.swift; sourceTree = ""; }; - 87765750E33B18AE518B6F447E6C87ED /* SmartCodable.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SmartCodable.debug.xcconfig; sourceTree = ""; }; - 8944B5E835D69F7ACF99BAE48649B2BF /* FBSnapshotTestController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestController.h; path = FBSnapshotTestCase/FBSnapshotTestController.h; sourceTree = ""; }; - 8A6BBDBDEEF349AAA722FA356CBA7BD9 /* main.c */ = {isa = PBXFileReference; includeInIndex = 1; name = main.c; path = src/main.c; sourceTree = ""; }; - 8BC254FD8EC10D39D0B946E545B0AC6D /* ConstraintMakerEditable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerEditable.swift; path = Sources/ConstraintMakerEditable.swift; sourceTree = ""; }; - 8C12AEF40FFC99AB7F38B2B64D66EE7E /* _SmartJSONDecoder+Unbox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "_SmartJSONDecoder+Unbox.swift"; sourceTree = ""; }; - 8CF972F529FCD52A4837EF7384E25630 /* UIApplication+StrictKeyWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIApplication+StrictKeyWindow.h"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h"; sourceTree = ""; }; - 8D3E80998BCA7EF85CC765918FD0D670 /* StatementPragma.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementPragma.swift; path = swift/source/abstract/StatementPragma.swift; sourceTree = ""; }; - 8D6B4B87B15CBF895D050929727FBC7F /* FBSnapshotTestCase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCase.m; path = FBSnapshotTestCase/FBSnapshotTestCase.m; sourceTree = ""; }; - 8D7BA7EC0C7015514C5CC8ECA03C5A70 /* WCDB.swift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = WCDB.swift.release.xcconfig; sourceTree = ""; }; - 8D8F51139F0FA15FEDE192F7F29A3781 /* Describable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Describable.swift; path = swift/source/abstract/Describable.swift; sourceTree = ""; }; - 8DA4771CF91F3004D3D65B79990DE177 /* queue.c */ = {isa = PBXFileReference; includeInIndex = 1; name = queue.c; path = src/queue.c; sourceTree = ""; }; - 8E60F4510824A7A8EADD930362F84E30 /* mutex_noop.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mutex_noop.c; path = src/mutex_noop.c; sourceTree = ""; }; - 8E63D643A1B5C6A2B7C0A46448402CEB /* ChainCall.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ChainCall.swift; path = swift/source/core/interface/ChainCall.swift; sourceTree = ""; }; - 8E7E6CC166BDB2FBE80EA3AEC615AA57 /* BTPrint-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTPrint-prefix.pch"; sourceTree = ""; }; - 8EBE6B1394A862F1ACAFA1EE0AE8D24E /* ColorTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ColorTransformer.swift; sourceTree = ""; }; - 8F2E09890770921E19347954E8967E50 /* IndexBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IndexBinding.swift; path = swift/source/core/binding/IndexBinding.swift; sourceTree = ""; }; - 8FFCB8A3A3DABA88D9B4E1ADB6B2BC15 /* BuiltInBridgeType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BuiltInBridgeType.swift; path = Source/BuiltInBridgeType.swift; sourceTree = ""; }; - 901AD1CA40244E43697CA8525620F3B2 /* ForeignKey.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ForeignKey.swift; path = swift/source/abstract/ForeignKey.swift; sourceTree = ""; }; - 9150B5DCEC6DD38F143FBDEE388906CE /* memjournal.c */ = {isa = PBXFileReference; includeInIndex = 1; name = memjournal.c; path = src/memjournal.c; sourceTree = ""; }; - 925381DED7E88D2040106861CAEFE6C8 /* WCDB.swift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "WCDB.swift-dummy.m"; sourceTree = ""; }; - 928E408AEF03BB6E25B32C26721E705A /* CleanJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CleanJSON.modulemap; sourceTree = ""; }; - 929712FD14C65CBAF44B3BA838DCFB36 /* _CleanJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = _CleanJSONDecoder.swift; path = Sources/CleanJSON/_CleanJSONDecoder.swift; sourceTree = ""; }; - 929C4FE20402ECA721BAE7E722B6E523 /* ConstraintInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsetTarget.swift; path = Sources/ConstraintInsetTarget.swift; sourceTree = ""; }; - 940A8C6613C7BC0BF47F245097A1BCAC /* fts3_write.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_write.c; path = ext/fts3/fts3_write.c; sourceTree = ""; }; - 944178E3D8552FB8678D163FCDF781F4 /* sqliteicu.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliteicu.h; path = ext/icu/sqliteicu.h; sourceTree = ""; }; - 94F201352441D0808E12B12C1B02950B /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+SingleValueDecodingContainer.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+SingleValueDecodingContainer.swift"; sourceTree = ""; }; - 95129AD448C6FA92BE25187E54E7D541 /* SmartEncodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartEncodable.swift; sourceTree = ""; }; - 953E4CFA5CA8CCBA3E6CA55F7CFF2BD8 /* vacuum.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vacuum.c; path = src/vacuum.c; sourceTree = ""; }; - 957AD6E6B2DEA9C2223DBD3581F63EBC /* TransformType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TransformType.swift; path = Source/TransformType.swift; sourceTree = ""; }; - 959A3546F4262DC0138394886AA3D28D /* notify.c */ = {isa = PBXFileReference; includeInIndex = 1; name = notify.c; path = src/notify.c; sourceTree = ""; }; + 87C56FECBDEE19803E1748DE1C16FBBA /* UIApplication+StrictKeyWindow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+StrictKeyWindow.m"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m"; sourceTree = ""; }; + 87EF2DCAFAACA539DB4A58A75FC36303 /* FBSnapshotTestCasePlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCasePlatform.h; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.h; sourceTree = ""; }; + 89305DC7AA8CF17C4DFF5582FDC4E381 /* SnapKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapKit-dummy.m"; sourceTree = ""; }; + 89D27D01563CE1DAAD49F56EC8284738 /* SmartCodable.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = SmartCodable.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 8ADD33B297AB30B353CFB5D0A4234E39 /* DateTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DateTransformer.swift; sourceTree = ""; }; + 8D31C1D12C0D9C516CE738486208A159 /* HandyJSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HandyJSON.h; path = Source/HandyJSON.h; sourceTree = ""; }; + 8EF8CFAD648CDD728E621EF9F95D03A0 /* JSONSingleValueEncodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONSingleValueEncodingContainer.swift; sourceTree = ""; }; + 8F3DB64808585AF7EC48453CC5E40015 /* EncodingCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = EncodingCache.swift; sourceTree = ""; }; + 9121AADFDAA9E940775A36390D6DDBC7 /* ToJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToJSON.swift; path = Sources/CleanJSON/ToJSON.swift; sourceTree = ""; }; + 91432EF00E1AB07F6B570628BF9725A7 /* JSONDecoderImpl+KeyedContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "JSONDecoderImpl+KeyedContainer.swift"; sourceTree = ""; }; + 91D961BD3D7E5A4FD5EFC37B4EF49FD4 /* HandyJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HandyJSON-umbrella.h"; sourceTree = ""; }; + 926AFEC77F93BCAD652BB781C5D0AA8C /* BTPrint-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BTPrint-dummy.m"; sourceTree = ""; }; + 93B6822011E346FDFA44C5A0CAB94482 /* BuiltInBasicType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BuiltInBasicType.swift; path = Source/BuiltInBasicType.swift; sourceTree = ""; }; + 95214B05E868BF779E006FD88F1F0B9D /* DecodingError+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "DecodingError+Extension.swift"; sourceTree = ""; }; + 96FC33890F5B9F948392563B47A573A0 /* SnapKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-umbrella.h"; sourceTree = ""; }; + 9771EF69C497A5113339604D439DBD71 /* SmartCodable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SmartCodable-dummy.m"; sourceTree = ""; }; 979486118B3E90C08386079D57962701 /* SnapKit */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SnapKit; path = SnapKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 97D90DEDEA77DAB3CC21506808D91533 /* BTBubble-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BTBubble-dummy.m"; sourceTree = ""; }; - 981FC3D828F7DDCD2F77A0BF2CEB5313 /* btree.c */ = {isa = PBXFileReference; includeInIndex = 1; name = btree.c; path = src/btree.c; sourceTree = ""; }; - 9930E634CA9F9592BA112E4EA073572B /* Error.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Error.swift; path = swift/source/util/Error.swift; sourceTree = ""; }; - 9A09037802A20D832A880AA28340A8C1 /* FBSnapshotTestCase-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-prefix.pch"; sourceTree = ""; }; - 9A0CDA24DDDB701970130A91AE5FA140 /* ConstraintView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintView.swift; path = Sources/ConstraintView.swift; sourceTree = ""; }; + 992A16CABA4C83CBEACADDABDE5021A8 /* SwiftSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftSupport.swift; path = FBSnapshotTestCase/SwiftSupport.swift; sourceTree = ""; }; + 995E5EF37D2EA75ADFF0B21D968E5B58 /* JSONEncoderImpl.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONEncoderImpl.swift; sourceTree = ""; }; + 9A4757260F219342EC59610827085045 /* ConstraintMaker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMaker.swift; path = Sources/ConstraintMaker.swift; sourceTree = ""; }; 9AB62CDC1D9A84669428234D73C264AF /* Pods-SmartCodable_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SmartCodable_Example-dummy.m"; sourceTree = ""; }; - 9AFCAB9E9753399E6A58D76D66B7B130 /* TableCodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableCodable.swift; path = swift/source/core/codable/TableCodable.swift; sourceTree = ""; }; - 9B544865E9FB982351862D454EB97A62 /* ConstraintDescription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDescription.swift; path = Sources/ConstraintDescription.swift; sourceTree = ""; }; - 9BC163C89756D7DD71745C9D0ED58162 /* sqliterk_column.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_column.c; path = repair/sqliterk_column.c; sourceTree = ""; }; - 9D577565B80212CC59E86358A09119B1 /* sqliterk.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk.c; path = repair/sqliterk.c; sourceTree = ""; }; - 9D5E5FF169696273D350DDAD938BA59C /* crypto.c */ = {isa = PBXFileReference; includeInIndex = 1; name = crypto.c; path = src/crypto.c; sourceTree = ""; }; + 9D5AD1AE1022A579A49D4DE848C3C5D9 /* PointerType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PointerType.swift; path = Source/PointerType.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9DD5BACBA6C6D7D9023F4EEAEF6AA63F /* HandyJSON.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HandyJSON.release.xcconfig; sourceTree = ""; }; - 9DDA253A371800B761863D370EB8DA28 /* SnapKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapKit-dummy.m"; sourceTree = ""; }; - 9E36FB803EEC5440AF34F62163B0EDD6 /* SmartCodable.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SmartCodable.release.xcconfig; sourceTree = ""; }; - 9E3A3F838435552834A4D0E6C267929F /* ColumnConstraintBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnConstraintBinding.swift; path = swift/source/core/binding/ColumnConstraintBinding.swift; sourceTree = ""; }; - 9EEBBB487C8AE88B5512D2789CC3EBB5 /* WCDB.swift-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "WCDB.swift-Info.plist"; sourceTree = ""; }; - 9F616208225C5B42B50ABA5F5267C29F /* Database.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Database.swift; path = swift/source/core/base/Database.swift; sourceTree = ""; }; - 9F8BF617506C58E3EDF6131E3780534E /* callback.c */ = {isa = PBXFileReference; includeInIndex = 1; name = callback.c; path = src/callback.c; sourceTree = ""; }; - 9FA4DFB85B8BF5A18EDB74A8189262F5 /* SnapKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-prefix.pch"; sourceTree = ""; }; - A0752EA93024C04D691ED9C4C27314C9 /* sqlite3.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = sqlite3.h; sourceTree = ""; }; - A17FFA6423420CF5D2CD5A85C44E4F88 /* util.c */ = {isa = PBXFileReference; includeInIndex = 1; name = util.c; path = src/util.c; sourceTree = ""; }; - A1BE8BC5AD3696828942B96191FFC93B /* fts3_tokenize_vtab.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_tokenize_vtab.c; path = ext/fts3/fts3_tokenize_vtab.c; sourceTree = ""; }; - A24DE9EEC0E48E6087452D0991A25DBB /* sqliterk_os.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_os.c; path = repair/sqliterk_os.c; sourceTree = ""; }; - A2BA444A4E60E7EA50A97DCF8F4CC456 /* sqliterk_crypto.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_crypto.c; path = repair/sqliterk_crypto.c; sourceTree = ""; }; - A343A2044144CB7474985FA357554BD0 /* fts3_tokenizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fts3_tokenizer.h; path = ext/fts3/fts3_tokenizer.h; sourceTree = ""; }; - A352B8E7226498116372CB1AD0618F54 /* rowset.c */ = {isa = PBXFileReference; includeInIndex = 1; name = rowset.c; path = src/rowset.c; sourceTree = ""; }; - A361C5D364F6A6DA615D350869696116 /* sqliterk_column.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_column.h; path = repair/sqliterk_column.h; sourceTree = ""; }; - A4CC74704F393D76FD2165D29F8C4069 /* FieldDescriptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FieldDescriptor.swift; path = Source/FieldDescriptor.swift; sourceTree = ""; }; + 9FAB40FD80A45A7E3594DC159F7D54B6 /* ColorTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ColorTransformer.swift; sourceTree = ""; }; + A0442ACE2BA5F7E00E86DA7955E7AF77 /* KeysMapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = KeysMapper.swift; sourceTree = ""; }; + A11B531AF457EC4F99F06F115FDE0A45 /* FBSnapshotTestCase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCase.m; path = FBSnapshotTestCase/FBSnapshotTestCase.m; sourceTree = ""; }; + A247AF8B486EBFFB5B5CED8A27FD6D94 /* _CleanJSONDecoder+Decode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+Decode.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+Decode.swift"; sourceTree = ""; }; + A370EE4D019ADFE65F2DC1FF9EDBA187 /* CleanJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CleanJSON-dummy.m"; sourceTree = ""; }; A4CFCEB2A58CA7A3CB15E26DD28CA8D6 /* Pods-SmartCodable_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-SmartCodable_Example"; path = Pods_SmartCodable_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A4D0796E3D77462A2F42DF4FD9C5BCF3 /* pragma.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = pragma.h; path = src/pragma.h; sourceTree = ""; }; - A4EB0C0E105B37698E256E0C139E5B82 /* DateFormatterTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DateFormatterTransform.swift; path = Source/DateFormatterTransform.swift; sourceTree = ""; }; - A517728630E48F320F0B505002BFD256 /* FBSnapshotTestCase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FBSnapshotTestCase.modulemap; sourceTree = ""; }; - A60871F481FE13AFE0AF788771BD15CE /* TableDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableDecoder.swift; path = swift/source/core/codable/TableDecoder.swift; sourceTree = ""; }; - A7758FB3B629E7C38E290756F49F3101 /* PointerType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PointerType.swift; path = Source/PointerType.swift; sourceTree = ""; }; - A81B9DCB1C5F346CFD0DDFE4DBB79691 /* CleanJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONDecoder.swift; path = Sources/CleanJSON/CleanJSONDecoder.swift; sourceTree = ""; }; - A860A482AA0D4015362C409845AF6F34 /* CleanJSON-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CleanJSON-Info.plist"; sourceTree = ""; }; - A892CB525DEAC1E1F53B41226E5AFC5E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - AA051B6194661AA53CBD57DF37336F10 /* SQLiteRepairKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SQLiteRepairKit.modulemap; sourceTree = ""; }; - AAF31A29B5ABB6F160DFCBA5CB8E203F /* SQLiteRepairKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SQLiteRepairKit-prefix.pch"; sourceTree = ""; }; - AC26795DE4514FE32D3094E1B9384FC6 /* BTBubble-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BTBubble-umbrella.h"; sourceTree = ""; }; - AD44D95A3B0AA90BECF82F884FAA3C5A /* userauth.c */ = {isa = PBXFileReference; includeInIndex = 1; name = userauth.c; path = ext/userauth/userauth.c; sourceTree = ""; }; - ADAA91299769BD42F20D8F8CD7793220 /* StatementVacuum.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementVacuum.swift; path = swift/source/abstract/StatementVacuum.swift; sourceTree = ""; }; - ADDAA04F64E571FD4FDEB5F3133A447A /* Debugging.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Debugging.swift; path = Sources/Debugging.swift; sourceTree = ""; }; - AE3301D1CE71A4E0C1D2991CAB2A9207 /* ConstraintOffsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintOffsetTarget.swift; path = Sources/ConstraintOffsetTarget.swift; sourceTree = ""; }; - AE6B62F1651CE843373519CDD60C5F25 /* HandyJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HandyJSON-prefix.pch"; sourceTree = ""; }; - AF7E6F369E3B04273EEA3F174700C2E0 /* btree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = btree.h; path = src/btree.h; sourceTree = ""; }; - B0F6A82607269E6FB6F472F6C4488DA3 /* mutex_wcdb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mutex_wcdb.h; path = src/mutex_wcdb.h; sourceTree = ""; }; - B1ABE47C1F1223A420137396A81E391B /* ConstraintRelation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelation.swift; path = Sources/ConstraintRelation.swift; sourceTree = ""; }; - B1ECB4EFC6697075F43D35D69C0F6BCE /* RowSelect.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RowSelect.swift; path = swift/source/core/interface/RowSelect.swift; sourceTree = ""; }; - B20F883B8D4C68B3B3B7937CF3DA069D /* StatementRollback.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementRollback.swift; path = swift/source/abstract/StatementRollback.swift; sourceTree = ""; }; - B27DA73869030B61A7DD375B3D22632A /* ConstraintViewDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintViewDSL.swift; path = Sources/ConstraintViewDSL.swift; sourceTree = ""; }; - B35C9C2671C107A19B97A31FB4CC5BEA /* ConstraintMaker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMaker.swift; path = Sources/ConstraintMaker.swift; sourceTree = ""; }; - B3CF92365D6AE0F35C3602CF6C0872AE /* WCDBOptimizedSQLCipher */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = WCDBOptimizedSQLCipher; path = sqlcipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B424B547BC415CB72334DBEE448A4DB1 /* sqliterk_util.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_util.c; path = repair/sqliterk_util.c; sourceTree = ""; }; - B49B1E6ADFC78844B1A8F500C06976E2 /* ColumnCodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnCodable.swift; path = swift/source/core/codable/ColumnCodable.swift; sourceTree = ""; }; - B4AE57587CB01377DE7465D672246876 /* WCDB.swift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = WCDB.swift.modulemap; sourceTree = ""; }; - B507A62DC4EBD3BB69182CD41E19AEDD /* BTBubble+Check.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Check.swift"; path = "BTBubble/Classes/BTBubble+Check.swift"; sourceTree = ""; }; - B508AD354731149BE19FE9B19292E30C /* URLTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = URLTransformer.swift; sourceTree = ""; }; + A4FA9C2F58756A6AFCF914B64DC8959B /* Transformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Transformer.swift; sourceTree = ""; }; + A698925A05268E73A17E232B6FB6FAC6 /* Patcher+Transformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Patcher+Transformer.swift"; sourceTree = ""; }; + A77DB2179984C4C073E5FC6BDCD19B77 /* BTBubble-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BTBubble-dummy.m"; sourceTree = ""; }; + A81A3A6F1AC972F8A54272A3F0CD7B26 /* JSONKeyedEncodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONKeyedEncodingContainer.swift; sourceTree = ""; }; + A8396A1DCA6FC67A7830D34F6F815289 /* BTBubble+Draw.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Draw.swift"; path = "BTBubble/Classes/BTBubble+Draw.swift"; sourceTree = ""; }; + A9389F909C87A9935163E0C9AF9629B5 /* SmartCodable-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SmartCodable-Info.plist"; sourceTree = ""; }; + AB1035777F9D0FAD25F91B78CF571685 /* ConstraintMakerFinalizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerFinalizable.swift; path = Sources/ConstraintMakerFinalizable.swift; sourceTree = ""; }; + ACA8ECF0DA97BC31739DBB05EDA01B23 /* SmartCodable.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SmartCodable.debug.xcconfig; sourceTree = ""; }; + ADD1B40612B0CE612E816E472F043F2F /* SmartKeyDecodingStrategy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartKeyDecodingStrategy.swift; sourceTree = ""; }; + ADDD58F0A7F5CBCD84256A572196E486 /* CustomDateFormatTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomDateFormatTransform.swift; path = Source/CustomDateFormatTransform.swift; sourceTree = ""; }; + B17DBF7CBD3616A875D3281F35287EA6 /* SmartDecodable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartDecodable.swift; sourceTree = ""; }; + B1A452E1BB4D2E97E82928F4C874C8C1 /* SmartJSONEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartJSONEncoder.swift; sourceTree = ""; }; + B2E248320C9CBA206187879E5FDFE4C6 /* _SpecialTreatmentEncoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = _SpecialTreatmentEncoder.swift; sourceTree = ""; }; + B3CC75B7FCBD0A88F04962B84E46D054 /* FBSnapshotTestCasePlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCasePlatform.m; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.m; sourceTree = ""; }; + B4E9A27193AA9BC77F718F28EA0E1B65 /* SmartJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartJSONDecoder.swift; sourceTree = ""; }; + B5D179B728984FF882E8BF4096799056 /* JSONDecoderImpl+unwrap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "JSONDecoderImpl+unwrap.swift"; sourceTree = ""; }; B66F7BC9A4DCD060099089C86B6DBC00 /* BTBubble */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = BTBubble; path = BTBubble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B68373D3DB223AC11F1B7D84FCDBFC8A /* ToJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToJSON.swift; path = Sources/CleanJSON/ToJSON.swift; sourceTree = ""; }; - B6FD93E2638B8D26614D584022725EA7 /* hash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = hash.h; path = src/hash.h; sourceTree = ""; }; - B753815544AFD5C6E0EBECDBE87DF183 /* vtab.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vtab.c; path = src/vtab.c; sourceTree = ""; }; - B780DB2E145B03662828DEC1C5D1132F /* ConstraintLayoutSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupport.swift; path = Sources/ConstraintLayoutSupport.swift; sourceTree = ""; }; - B81E6BEF09C7E97AF72776F1CA7F474A /* LayoutConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraint.swift; path = Sources/LayoutConstraint.swift; sourceTree = ""; }; - B85B1B1333F12E9C10C98F336EB35B05 /* sqliteInt.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliteInt.h; path = src/sqliteInt.h; sourceTree = ""; }; - B879FC7FFD1918AD9A99D212BB3DA7FB /* mem3.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mem3.c; path = src/mem3.c; sourceTree = ""; }; - BA8A83EBBBB8A4450E2DF18764BD5569 /* WCDBOptimizedSQLCipher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = WCDBOptimizedSQLCipher.modulemap; sourceTree = ""; }; - BBC9E37E1231F7C47C1FF217714CB44C /* AnyExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnyExtensions.swift; path = Source/AnyExtensions.swift; sourceTree = ""; }; - BC0D345CD33B982912326FCB76C211C2 /* TableConstraintBinding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TableConstraintBinding.swift; path = swift/source/core/binding/TableConstraintBinding.swift; sourceTree = ""; }; - BC3729C5B5DB3FDFBE89ADB7BC30CFED /* SnapKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.debug.xcconfig; sourceTree = ""; }; - BC50E104171DCA96B772A10AA0564122 /* ModuleArgument.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ModuleArgument.swift; path = swift/source/abstract/ModuleArgument.swift; sourceTree = ""; }; - BC9FD46ECA8E8E5EF9E6B7EB1AF5495D /* ConstraintAttributes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintAttributes.swift; path = Sources/ConstraintAttributes.swift; sourceTree = ""; }; - BCADA2E9A3086D97A8BCB6A43D4E9D67 /* Select.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Select.swift; path = swift/source/core/interface/Select.swift; sourceTree = ""; }; - BE9E2E9B8EEBD6E444845703ABB17FA8 /* Deserializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Deserializer.swift; path = Source/Deserializer.swift; sourceTree = ""; }; - BF1352FCE3039BCA9739C2333B9AA5EE /* Statement.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Statement.swift; path = swift/source/abstract/Statement.swift; sourceTree = ""; }; - BFA871D4B31BEA3D4DF3421A0453A0B6 /* UIImage+Snapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Snapshot.m"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.m"; sourceTree = ""; }; - C01B5E0468FB391500B5CE91906AA1CA /* UIImage+Diff.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Diff.h"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.h"; sourceTree = ""; }; - C0578B106653292AA1BCD11BC78ECD48 /* OrderTerm.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OrderTerm.swift; path = swift/source/abstract/OrderTerm.swift; sourceTree = ""; }; - C0CCC34D442A08D6E9FEECCD26D1E3B7 /* crypto.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = crypto.h; path = src/crypto.h; sourceTree = ""; }; - C0E5DF2BD31809E3F1A4018A2E009037 /* pager.c */ = {isa = PBXFileReference; includeInIndex = 1; name = pager.c; path = src/pager.c; sourceTree = ""; }; - C14D61C7AE59E97D0F73C27659D8489D /* sqlite3userauth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqlite3userauth.h; path = ext/userauth/sqlite3userauth.h; sourceTree = ""; }; - C1662A646B256DAAC436E92852D15012 /* URLTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLTransform.swift; path = Source/URLTransform.swift; sourceTree = ""; }; - C177859E1A60F619FF28EED9334F6BFC /* MangledName.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MangledName.swift; path = Source/MangledName.swift; sourceTree = ""; }; - C3208D7D718A79BBC3B9384E32256F6A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - C357740AEE6772021A24F0E4114A600F /* CleanJSONDecodingStorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONDecodingStorage.swift; path = Sources/CleanJSON/CleanJSONDecodingStorage.swift; sourceTree = ""; }; - C3C2131D87E7F2B2C1601DBFDB5E83BD /* ExtendCustomModelType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExtendCustomModelType.swift; path = Source/ExtendCustomModelType.swift; sourceTree = ""; }; - C4C12BFAA6F02D6D9B0F42E75644DD5E /* FBSnapshotTestCase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FBSnapshotTestCase-dummy.m"; sourceTree = ""; }; - C538963150450AD6377ACBE6ECAB0F31 /* BTPrint.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTPrint.debug.xcconfig; sourceTree = ""; }; - C54DA92E53C8E33D0D0C63CDF41C84CF /* DataTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DataTransform.swift; path = Source/DataTransform.swift; sourceTree = ""; }; - C5CDB7508D26894D5B12C0A1D125803A /* BTBubble+Draw.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Draw.swift"; path = "BTBubble/Classes/BTBubble+Draw.swift"; sourceTree = ""; }; - C5DFE21D0BEE989AE9E8287E5BEE62A5 /* BTBubble+Menu.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Menu.swift"; path = "BTBubble/Classes/BTBubble+Menu.swift"; sourceTree = ""; }; - C63C50EBF0AE1A7E3E83D4462CD73A8D /* fts3_expr.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_expr.c; path = ext/fts3/fts3_expr.c; sourceTree = ""; }; - C6BABF528CFB1403AB76736DC9D8A507 /* prepare.c */ = {isa = PBXFileReference; includeInIndex = 1; name = prepare.c; path = src/prepare.c; sourceTree = ""; }; - C8053B0C2844CD59CE3E68D5FC9DDE5B /* ColumnType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ColumnType.swift; path = swift/source/abstract/ColumnType.swift; sourceTree = ""; }; - C85D39B63CA259934A33F2B43CA2305E /* BuiltInBasicType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BuiltInBasicType.swift; path = Source/BuiltInBasicType.swift; sourceTree = ""; }; - C88B551F69097A3D9A651BB19E4806AE /* Tracer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tracer.swift; path = swift/source/abstract/Tracer.swift; sourceTree = ""; }; - C8D5FA619E1FFE76299F63EA49B6497C /* TransformOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TransformOf.swift; path = Source/TransformOf.swift; sourceTree = ""; }; - C9285283C0400C69E185F4F4E5C3699A /* LogItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LogItem.swift; sourceTree = ""; }; - C9D753BDFA887910415613027FC5070B /* Master.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Master.swift; path = swift/source/builtin/Master.swift; sourceTree = ""; }; - CC539335DC60778548E801CDB7F2D02F /* global.c */ = {isa = PBXFileReference; includeInIndex = 1; name = global.c; path = src/global.c; sourceTree = ""; }; - CC7C3FEF64C65495CFE6D7B9F95A1355 /* CleanJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CleanJSON-prefix.pch"; sourceTree = ""; }; - CCAC6A3BDBBBA93A2573EDA5CD4CB7FB /* ISO8601DateTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ISO8601DateTransform.swift; path = Source/ISO8601DateTransform.swift; sourceTree = ""; }; + B7FDF252ED60310F04697FD38BA56AE6 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + B884BE2A9A48EFA0DCB33348C5EECBCA /* BTBubble.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BTBubble.modulemap; sourceTree = ""; }; + B8F06552F963B43848600AFDC8043A19 /* CleanDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanDecoder.swift; path = Sources/CleanJSON/CleanDecoder.swift; sourceTree = ""; }; + B9E5E84322D1072C445D51381EACDD7D /* DecodingError+CleanJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DecodingError+CleanJSON.swift"; path = "Sources/CleanJSON/DecodingError+CleanJSON.swift"; sourceTree = ""; }; + B9E9FCD5E63CE808B8773D040F1E2BA8 /* FBSnapshotTestCase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FBSnapshotTestCase-dummy.m"; sourceTree = ""; }; + BAF69AF530FDB1A1819B8E00A3E4775A /* ReflectionHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ReflectionHelper.swift; path = Source/ReflectionHelper.swift; sourceTree = ""; }; + BC6DB121D8A9523A91FDAB8376BE09FD /* DataTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DataTransform.swift; path = Source/DataTransform.swift; sourceTree = ""; }; + BF34C278263A81DD03B77202C061698C /* CleanJSONDecodingStorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONDecodingStorage.swift; path = Sources/CleanJSON/CleanJSONDecodingStorage.swift; sourceTree = ""; }; + C00DB4F15575B9722480D9D45738DD49 /* JSONDecoderImpl+SingleValueContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "JSONDecoderImpl+SingleValueContainer.swift"; sourceTree = ""; }; + C236F0CDFBBFF56E8E482E41A943E19E /* BTBubble+Animation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "BTBubble+Animation.swift"; path = "BTBubble/Classes/BTBubble+Animation.swift"; sourceTree = ""; }; + C2C99A53F71055734332736B13A49C28 /* SnapKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-prefix.pch"; sourceTree = ""; }; + C30DC42DFE9E9BEB719E4821761599C5 /* EnumTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EnumTransform.swift; path = Source/EnumTransform.swift; sourceTree = ""; }; + C4749570A46F497B425767CB4569ADF9 /* HelpingMapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpingMapper.swift; path = Source/HelpingMapper.swift; sourceTree = ""; }; + C4750BB7C125054792532A6CE7EFC1F8 /* BTPrint-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "BTPrint-Info.plist"; sourceTree = ""; }; + C53C2DBE2FECF12DA6C33264A027EC82 /* ConstraintDirectionalInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsetTarget.swift; path = Sources/ConstraintDirectionalInsetTarget.swift; sourceTree = ""; }; + C548E3997850B2E10E6E8D21CACB81A3 /* CleanJSON.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CleanJSON.release.xcconfig; sourceTree = ""; }; + C5688C4B8AAD0B0302EE6D8567AB0A03 /* UIImage+Compare.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Compare.m"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.m"; sourceTree = ""; }; + C57A6E8C38153E40B8497C02204DF7F4 /* ISO8601DateTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ISO8601DateTransform.swift; path = Source/ISO8601DateTransform.swift; sourceTree = ""; }; + C6D3430E32742C8A84D354226C873C6C /* CleanJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CleanJSON-umbrella.h"; sourceTree = ""; }; + C7BBDFD017622786401A39F6BD9686C8 /* _CleanJSONDecoder+Unbox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+Unbox.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+Unbox.swift"; sourceTree = ""; }; + C89E8087BFA786A66175CFC23BA8FF12 /* JSONDecoderImpl.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONDecoderImpl.swift; sourceTree = ""; }; + C958AC7215CB092EEC6FA33BD843AC29 /* ConstraintViewDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintViewDSL.swift; path = Sources/ConstraintViewDSL.swift; sourceTree = ""; }; + CC6BD8F9EB57322C72A42B7031485790 /* ConstraintMakerRelatable+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintMakerRelatable+Extensions.swift"; path = "Sources/ConstraintMakerRelatable+Extensions.swift"; sourceTree = ""; }; CD54121DDA84872534168702B5F92950 /* HandyJSON */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = HandyJSON; path = HandyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CE826E7F05CF3F8586C677CB5A2530B5 /* random.c */ = {isa = PBXFileReference; includeInIndex = 1; name = random.c; path = src/random.c; sourceTree = ""; }; - CEA6C3D31D4A4A55C19A9EA22E0F3C2A /* ContextDescriptorType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContextDescriptorType.swift; path = Source/ContextDescriptorType.swift; sourceTree = ""; }; - CED8325151406ED11C82AF15BBFD7E6E /* Operable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Operable.swift; path = swift/source/abstract/Operable.swift; sourceTree = ""; }; - CEF047CA737FB19838BEC0244141C05B /* StatementTransaction.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementTransaction.swift; path = swift/source/abstract/StatementTransaction.swift; sourceTree = ""; }; + CDD07779AA8B42688ED0FF74BACC5AA5 /* AnyExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnyExtensions.swift; path = Source/AnyExtensions.swift; sourceTree = ""; }; CF572B5B26ACF0A775C07589992A5507 /* Pods-SmartCodable_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SmartCodable_Example.debug.xcconfig"; sourceTree = ""; }; - CF59ACCBC088180B9DDF32F0F236A4E3 /* sqlite3rbu.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqlite3rbu.c; path = ext/rbu/sqlite3rbu.c; sourceTree = ""; }; - CFCDD063DFADDF236ABB25163EB4A195 /* fts3_hash.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_hash.c; path = ext/fts3/fts3_hash.c; sourceTree = ""; }; - D02525015C11C983A716B56C77A390BA /* os_unix.c */ = {isa = PBXFileReference; includeInIndex = 1; name = os_unix.c; path = src/os_unix.c; sourceTree = ""; }; - D05D3A4DC15E54B38CB174AB1707F02C /* WCDBOptimizedSQLCipher.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = WCDBOptimizedSQLCipher.release.xcconfig; sourceTree = ""; }; - D07518FFD2D8665D6174ADB9E47C25D2 /* DateTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DateTransform.swift; path = Source/DateTransform.swift; sourceTree = ""; }; - D09AE90122BA076289207672D92C0950 /* Patcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Patcher.swift; sourceTree = ""; }; - D18D6541EFE81AFDF8F5EB531B779D4D /* LayoutConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraintItem.swift; path = Sources/LayoutConstraintItem.swift; sourceTree = ""; }; - D28489E1C38C95EF1D07BF0CD0A85216 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - D28D7943409E3C2F68D7F7BFD3C05A1C /* ConstraintMakerPrioritizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerPrioritizable.swift; path = Sources/ConstraintMakerPrioritizable.swift; sourceTree = ""; }; - D292372E6836D90D57FB9F067F486A11 /* DecodingError+CleanJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DecodingError+CleanJSON.swift"; path = "Sources/CleanJSON/DecodingError+CleanJSON.swift"; sourceTree = ""; }; - D2B3E35A4BC256533E927EE1175DFF3E /* UIApplication+StrictKeyWindow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+StrictKeyWindow.m"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m"; sourceTree = ""; }; - D36CFDC8FE52D5BF5257BBC8979DE5EC /* sqliterk_output.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = sqliterk_output.cpp; path = repair/sqliterk_output.cpp; sourceTree = ""; }; - D410A3C5F8C66EF9FB1F780E3A614657 /* CleanJSONKeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONKeyedDecodingContainer.swift; path = Sources/CleanJSON/CleanJSONKeyedDecodingContainer.swift; sourceTree = ""; }; - D54143E7A4BC63635B0089DB6810A04A /* wal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = wal.h; path = src/wal.h; sourceTree = ""; }; - D576389A8088EF7132E5C2014B4EE239 /* icu.c */ = {isa = PBXFileReference; includeInIndex = 1; name = icu.c; path = ext/icu/icu.c; sourceTree = ""; }; - D6C3547D57598A7565784581664A1EB4 /* ReflectionHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ReflectionHelper.swift; path = Source/ReflectionHelper.swift; sourceTree = ""; }; - D72D10260E32B90F95F2E7373E81C0C4 /* Transformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Transformer.swift; sourceTree = ""; }; - D8501160FCCFA343E417A66AA91DF92B /* CleanJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CleanJSON-umbrella.h"; sourceTree = ""; }; - D902F67F84D016160BC9C30B93A8F564 /* mutex_wcdb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = mutex_wcdb.c; path = src/mutex_wcdb.c; sourceTree = ""; }; - D987A5E4DDCE06D16CADF70907060EC5 /* loadext.c */ = {isa = PBXFileReference; includeInIndex = 1; name = loadext.c; path = src/loadext.c; sourceTree = ""; }; + CFC3023119381C8AA8F1A4F4106F012A /* ConstraintOffsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintOffsetTarget.swift; path = Sources/ConstraintOffsetTarget.swift; sourceTree = ""; }; + CFE40591DCBDB38549AD0FC756F3D616 /* ConstraintView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintView.swift; path = Sources/ConstraintView.swift; sourceTree = ""; }; + D0EEB810E2BEEE8D6FDAC45521E2B95A /* JSONValue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONValue.swift; sourceTree = ""; }; + D20FD964253D6C1E0040497B2CA5505E /* LayoutConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraintItem.swift; path = Sources/LayoutConstraintItem.swift; sourceTree = ""; }; + D283527F80A00FBB2FF5776A4E3B27B2 /* UIImage+Diff.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Diff.h"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.h"; sourceTree = ""; }; + D8123B10463E4148BBE847951CD834B0 /* BTBubble.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTBubble.release.xcconfig; sourceTree = ""; }; D9B8AA14A5BB1D0CE3A003CB6A566265 /* CleanJSON */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = CleanJSON; path = CleanJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D9E3BCE9634968B8A180F21A6AD2D46D /* BTBubble.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BTBubble.debug.xcconfig; sourceTree = ""; }; - DA2AB63F2AC5AC4FBB2A1B85A3A1BB92 /* HandlePool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HandlePool.swift; path = swift/source/core/base/HandlePool.swift; sourceTree = ""; }; - DA345BD674D6C7F2AFDCCD4E5A6520B1 /* HandyJSON-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HandyJSON-Info.plist"; sourceTree = ""; }; - DADAE210A27CFC78F890E11F91CDF3B7 /* WCDBOptimizedSQLCipher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "WCDBOptimizedSQLCipher-dummy.m"; sourceTree = ""; }; - DC652D711B63F8C1721F16CB2979AE0B /* BTBubbleConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTBubbleConfig.swift; path = BTBubble/Classes/BTBubbleConfig.swift; sourceTree = ""; }; - DC8CB60731C501F663A8ABBBFBAC4FCC /* FBSnapshotTestCase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.debug.xcconfig; sourceTree = ""; }; - DC98C8117F3B1431C854A9C6B4F8FE02 /* _CleanJSONDecoder+Decode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+Decode.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+Decode.swift"; sourceTree = ""; }; - DCE628DAB731CE9CF30F4A4CA4F2DD41 /* BTPrint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTPrint.swift; path = BTPrint/Classes/BTPrint.swift; sourceTree = ""; }; - DDB2EB56477F0F500E5E6BC9306CD760 /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Source/Configuration.swift; sourceTree = ""; }; - E07019FEB983E7289826370A121CFF96 /* Optional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Optional.swift; path = swift/source/util/Optional.swift; sourceTree = ""; }; - E15E404E75C9D493CD986005D7C5E51F /* StatementExplain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementExplain.swift; path = swift/source/abstract/StatementExplain.swift; sourceTree = ""; }; + DB06E31B883A63C5DE4A5A6308F36C8F /* CleanJSONDecoder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CleanJSONDecoder.swift; path = Sources/CleanJSON/CleanJSONDecoder.swift; sourceTree = ""; }; + DC816DCD26D7E20707BD2C4B66521329 /* FBSnapshotTestCase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FBSnapshotTestCase.modulemap; sourceTree = ""; }; + DCD54B400F0BA763829F393B36FC4C7F /* CleanJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CleanJSON.modulemap; sourceTree = ""; }; + DD91016CD3E4DB108E6B6B782539B2EC /* Constraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Constraint.swift; path = Sources/Constraint.swift; sourceTree = ""; }; + DDEF3ACF04599EB1C214870D993C7153 /* ConstraintDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDSL.swift; path = Sources/ConstraintDSL.swift; sourceTree = ""; }; E1687BCA2D5089035366568970461716 /* Pods-SmartCodable_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SmartCodable_Tests-Info.plist"; sourceTree = ""; }; - E24C10B99ADAD73E210FB8245ED8197B /* treeview.c */ = {isa = PBXFileReference; includeInIndex = 1; name = treeview.c; path = src/treeview.c; sourceTree = ""; }; - E3C3826A17E7079B5E9B8EF5E0726A8B /* sqliterk_values.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_values.h; path = repair/sqliterk_values.h; sourceTree = ""; }; + E20ABA9C7B9C59A9D3A5EA7AB0215871 /* TransformType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TransformType.swift; path = Source/TransformType.swift; sourceTree = ""; }; + E30EB7375ADE85CDDB7E41CEAB4FB6D5 /* BTPrint.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = BTPrint.modulemap; sourceTree = ""; }; E3F09186EE217FC9713BA39404EB7B24 /* Pods-SmartCodable_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SmartCodable_Tests-umbrella.h"; sourceTree = ""; }; - E4AF1DDFA0BFD4D141DC95A23E60E21E /* expr.c */ = {isa = PBXFileReference; includeInIndex = 1; name = expr.c; path = src/expr.c; sourceTree = ""; }; - E4CAFE90E23A817910BA25BDC1390D64 /* os.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = os.h; path = src/os.h; sourceTree = ""; }; - E554DEBB8837193A575EA37F69484063 /* attach.c */ = {isa = PBXFileReference; includeInIndex = 1; name = attach.c; path = src/attach.c; sourceTree = ""; }; - E5B4B1A682E2866B6A4A07E9208DAA3C /* vxworks.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = vxworks.h; path = src/vxworks.h; sourceTree = ""; }; - E5C698A33CA71DF66125CB48E115C9D1 /* fts3_aux.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_aux.c; path = ext/fts3/fts3_aux.c; sourceTree = ""; }; E5FA84A6FC991F1497F1DC0F7EA5CAD8 /* Pods-SmartCodable_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SmartCodable_Tests-dummy.m"; sourceTree = ""; }; - E690F4F3A52E7BD1C7B5AEF2B5DA6211 /* vdbeapi.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbeapi.c; path = src/vdbeapi.c; sourceTree = ""; }; - E6FC37377401182941FFB20A1035A933 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; - E78CA67C1117E52EF3FC13EB351A6819 /* DecodingProcessCoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DecodingProcessCoordinator.swift; sourceTree = ""; }; - E7F41D39907C3886957DEB2668992022 /* _CleanJSONDecoder+Unbox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "_CleanJSONDecoder+Unbox.swift"; path = "Sources/CleanJSON/_CleanJSONDecoder+Unbox.swift"; sourceTree = ""; }; - E871449A711764164F5DF40EE5109741 /* Declare.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Declare.swift; path = swift/source/core/interface/Declare.swift; sourceTree = ""; }; - E9E6026DFD06EAF5D78CF289D189A4AB /* UIImage+Compare.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Compare.h"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.h"; sourceTree = ""; }; - EB44A0EAF3083A0C1BB831A625B3A464 /* sqliterk_api.c */ = {isa = PBXFileReference; includeInIndex = 1; name = sqliterk_api.c; path = repair/sqliterk_api.c; sourceTree = ""; }; - EB6F7BA0DB362E9C44D65D67B447711D /* func.c */ = {isa = PBXFileReference; includeInIndex = 1; name = func.c; path = src/func.c; sourceTree = ""; }; - EC222A9A63C304EB2AA02877164C9C90 /* FBSnapshotTestCase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCase.h; path = FBSnapshotTestCase/FBSnapshotTestCase.h; sourceTree = ""; }; - EC269ED89F5E95338D486A4341D130E3 /* fts3_tokenizer.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_tokenizer.c; path = ext/fts3/fts3_tokenizer.c; sourceTree = ""; }; - EC4A1138AA274CD1E4839F0548F25126 /* ConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintItem.swift; path = Sources/ConstraintItem.swift; sourceTree = ""; }; - EC9FF687080036A8654DA415051A4F52 /* fault.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fault.c; path = src/fault.c; sourceTree = ""; }; - ED36361B8D8564C73918F7F46E942300 /* SQLiteRepairKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SQLiteRepairKit-umbrella.h"; sourceTree = ""; }; - EDF7058B96B59956D0341D5EE8DB387B /* SmartLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartLog.swift; sourceTree = ""; }; + E658F388F01C72599CA75537950B6095 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + E7D0C8FFA3D3F1791A00D06DA9FB06C3 /* OtherExtension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OtherExtension.swift; path = Source/OtherExtension.swift; sourceTree = ""; }; + E807ABEAA7D69B696DEF09C5E71FF4F5 /* SmartColor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartColor.swift; sourceTree = ""; }; + EA87DC4C55FBD71FD524E23BC5B638D4 /* Patcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Patcher.swift; sourceTree = ""; }; + EBDE8674ED579EE94A0773028BD44AF1 /* CaseDefaultable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CaseDefaultable.swift; path = Sources/CleanJSON/CaseDefaultable.swift; sourceTree = ""; }; + EC81D310210EE3584DF75E7C318F9318 /* EnumType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EnumType.swift; path = Source/EnumType.swift; sourceTree = ""; }; EE3F9FF6983083751E8AF8D756034C35 /* Pods-SmartCodable_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SmartCodable_Tests.release.xcconfig"; sourceTree = ""; }; - EF0FA79118EA6C707BFE21F070594989 /* ConstraintMultiplierTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMultiplierTarget.swift; path = Sources/ConstraintMultiplierTarget.swift; sourceTree = ""; }; - EF792627DE1714E38E8A9B2C7DA6A6B2 /* CustomDateFormatTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomDateFormatTransform.swift; path = Source/CustomDateFormatTransform.swift; sourceTree = ""; }; - EFE265BEFD53265D1B57FD37F6C1C080 /* sqliterk_pager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_pager.h; path = repair/sqliterk_pager.h; sourceTree = ""; }; - F16BCF96DA4A6F9BAA3D405212DD2906 /* Selectable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Selectable.swift; path = swift/source/core/interface/Selectable.swift; sourceTree = ""; }; - F3BD359F43CC6E82E7AC095DEFB667F6 /* Constraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Constraint.swift; path = Sources/Constraint.swift; sourceTree = ""; }; - F4A523DD234E18A60AF35F11CB72F42B /* os_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = os_common.h; path = src/os_common.h; sourceTree = ""; }; - F56261BCBCA2343ACB3164AE2B218462 /* LiteralValue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LiteralValue.swift; path = swift/source/abstract/LiteralValue.swift; sourceTree = ""; }; - F5F4960C860E51A6192EB670A1528988 /* CleanJSON.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CleanJSON.release.xcconfig; sourceTree = ""; }; - F628734F4AD8AC92C14058127679E7F3 /* SmartJSONKeyedDecodingContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartJSONKeyedDecodingContainer.swift; sourceTree = ""; }; - F631CC802E2701AD6DEAB71A9B7134CB /* StatementAttach.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementAttach.swift; path = swift/source/abstract/StatementAttach.swift; sourceTree = ""; }; - F63E4EB6FB734F947641DABA8C75AF07 /* legacy.c */ = {isa = PBXFileReference; includeInIndex = 1; name = legacy.c; path = src/legacy.c; sourceTree = ""; }; - F6A8B52AB6EF90B11566E30055201070 /* walker.c */ = {isa = PBXFileReference; includeInIndex = 1; name = walker.c; path = src/walker.c; sourceTree = ""; }; - F6AEFAF46A1EB958A79BAB5E3AE57152 /* UIImage+Snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Snapshot.h"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.h"; sourceTree = ""; }; - F726DF8A247CF9E3ED50B8EAA5957CFF /* vdbesort.c */ = {isa = PBXFileReference; includeInIndex = 1; name = vdbesort.c; path = src/vdbesort.c; sourceTree = ""; }; - F73913468036FE8ADDE2D7B47A50BB4C /* Tagged.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tagged.swift; path = swift/source/util/Tagged.swift; sourceTree = ""; }; - F77B4DD50B4E2BA5873C6AB52E4A8664 /* btreeInt.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = btreeInt.h; path = src/btreeInt.h; sourceTree = ""; }; - F83AA16D87731A9D1F4DBD9B22E0F7B5 /* WCDBOptimizedSQLCipher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "WCDBOptimizedSQLCipher-umbrella.h"; sourceTree = ""; }; - F92DEA4DA3E1E8E57E1E048E7AD51789 /* sqliterk_util.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = sqliterk_util.h; path = repair/sqliterk_util.h; sourceTree = ""; }; - F9BFA8B0590A57660EC2A37A517822E3 /* ConstraintConstantTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConstantTarget.swift; path = Sources/ConstraintConstantTarget.swift; sourceTree = ""; }; - FA773D1F7222071AA66218F4A74E3199 /* PrintFormat.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PrintFormat.swift; path = BTPrint/Classes/PrintFormat.swift; sourceTree = ""; }; - FAF9A5EA944619747B64BF79AEFCAB71 /* StatementDelete.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StatementDelete.swift; path = swift/source/abstract/StatementDelete.swift; sourceTree = ""; }; - FC8E9C700F20DBFB07454F509557FF17 /* ConstraintView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintView+Extensions.swift"; path = "Sources/ConstraintView+Extensions.swift"; sourceTree = ""; }; - FCEDA3C22B4FE876F9B1AE3E0300A4C9 /* SmartSONUnkeyedDecodingContainer+decode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SmartSONUnkeyedDecodingContainer+decode.swift"; sourceTree = ""; }; - FDC0F420686D5E03E5291BD62C6B6F99 /* Delete.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Delete.swift; path = swift/source/core/interface/Delete.swift; sourceTree = ""; }; - FDC31AE155953A80BB668497C4AC2BA0 /* fts3_tokenizer1.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fts3_tokenizer1.c; path = ext/fts3/fts3_tokenizer1.c; sourceTree = ""; }; - FE71CAA940B03B2DDA72A6A70DA38BFC /* SmartCodable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SmartCodable-dummy.m"; sourceTree = ""; }; - FE9E48CF5B436F03A644A3F2079E06A5 /* ConstraintMakerRelatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerRelatable.swift; path = Sources/ConstraintMakerRelatable.swift; sourceTree = ""; }; + EE7E7A774098C77B700C918B4B303354 /* BubbleTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BubbleTools.swift; path = BTBubble/Classes/BubbleTools.swift; sourceTree = ""; }; + EEAB8D6BB2A7369CCEF3D49B4BB21A9D /* CleanJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CleanJSON-prefix.pch"; sourceTree = ""; }; + F09645CD0AE835FD6F2CC1C70F2768E6 /* BTBubble.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BTBubble.swift; path = BTBubble/Classes/BTBubble.swift; sourceTree = ""; }; + F1D73F882F8E812397C7CC5B0A6618CD /* SafeDictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SafeDictionary.swift; sourceTree = ""; }; + F1F4D4D87CBE3DA68AFC92D6F05636AF /* ConstraintRelatableTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelatableTarget.swift; path = Sources/ConstraintRelatableTarget.swift; sourceTree = ""; }; + F324FE66E2BF9B4B5B507729C64FD069 /* Typealiases.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Typealiases.swift; path = Sources/Typealiases.swift; sourceTree = ""; }; + F36F08B193D052643664F581E6D09590 /* JSONParser.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = JSONParser.swift; sourceTree = ""; }; + F3DD3A510DCBD287B46973C5625A7FB1 /* ConstraintAttributes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintAttributes.swift; path = Sources/ConstraintAttributes.swift; sourceTree = ""; }; + F593D03921D2C6F913665801765ECADC /* SmartCodable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SmartCodable-umbrella.h"; sourceTree = ""; }; + F8C4BD4F4718E6FA4AC7DEA7CFD13293 /* FBSnapshotTestCase-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-prefix.pch"; sourceTree = ""; }; + F9693744257055D6E8D886301B98967F /* SnapKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.release.xcconfig; sourceTree = ""; }; + FA5EA7509BA3790A709778D9D36944E7 /* HandyJSON-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HandyJSON-Info.plist"; sourceTree = ""; }; + FAA37D00854B1424AE598ADE8E254D07 /* SmartAny.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SmartAny.swift; sourceTree = ""; }; + FB8DBD5CFA5CEBDCE3E21C0F74DF249C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + FCBDA27A176AE2D1C34BA797339DE8BB /* ConstraintMakerExtendable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerExtendable.swift; path = Sources/ConstraintMakerExtendable.swift; sourceTree = ""; }; + FD311A04C42FFDF8D95E30DC09B7EA57 /* ConstraintMakerRelatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerRelatable.swift; path = Sources/ConstraintMakerRelatable.swift; sourceTree = ""; }; + FD9C9CD93F7F692FE8121F7F78EE6DB8 /* NSDecimalNumberTransform.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NSDecimalNumberTransform.swift; path = Source/NSDecimalNumberTransform.swift; sourceTree = ""; }; + FE716DB85C8936F875B13305FA42C410 /* DataTransformer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DataTransformer.swift; sourceTree = ""; }; + FEB73C0BFC8A0BCE1F336584FF0D0236 /* Patcher+Provider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Patcher+Provider.swift"; sourceTree = ""; }; + FF1E4A64EAB2DB18EB9CAD95399FE5C9 /* SnapKit-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapKit-Info.plist"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1081,36 +510,35 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 24F210FE791EABA40F88F126F26F2C70 /* Frameworks */ = { + 2E43F8ADC875BC80E2A873F01E86FB3B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A578AD0AC1B114DD99F8E8C44E7D6E25 /* Foundation.framework in Frameworks */, + DF493E247E463CAC344C15784C9EF5AC /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 432508833C2857AC2B59098AE7E52E38 /* Frameworks */ = { + 50308E260B9FA8E4E237EF74B1479856 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BBDCCA2C3EA47E20E98B465C3D2EFCCE /* Foundation.framework in Frameworks */, - 431AAFBB20F0A2F30909DE889C34FE7F /* Security.framework in Frameworks */, + 1B8CE6509886B2FF237F5844B9C64C8B /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 50308E260B9FA8E4E237EF74B1479856 /* Frameworks */ = { + 5BFADEC849BD22C6CD97E83544F3E6C1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1B8CE6509886B2FF237F5844B9C64C8B /* Foundation.framework in Frameworks */, + 5CCB87A1A86D7C03A5D678B262B37071 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5BFADEC849BD22C6CD97E83544F3E6C1 /* Frameworks */ = { + 81AB633758722BCEBBC343F8868CA1E1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5CCB87A1A86D7C03A5D678B262B37071 /* Foundation.framework in Frameworks */, + 2C16E71C31FE60E1F5DB7FD9D5E56E12 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1149,73 +577,39 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - F715C66328463B5C993B81AB0FE02F75 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2F53741EC84A0BE1806E28F79E3F331D /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F751BAAE56D8FE399B415F5705050E96 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ADC27F881811D6E2247529ECF84FBFD2 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F929D5DFC96C72A9863CDE240F75BDC6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 018CC6BBD089090F514FF8AFF8606672 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 00F973FF64003D3142BC9125D9FBBB09 /* Support Files */ = { + 049FFF5761BF7F049DF9C98EFCC022EF /* FBSnapshotTestCase */ = { isa = PBXGroup; children = ( - BA8A83EBBBB8A4450E2DF18764BD5569 /* WCDBOptimizedSQLCipher.modulemap */, - DADAE210A27CFC78F890E11F91CDF3B7 /* WCDBOptimizedSQLCipher-dummy.m */, - 3F0C0136BF06270C5D625F26FC0A7E81 /* WCDBOptimizedSQLCipher-Info.plist */, - 5798E3AE0C35A0234890311B4DDB6BAA /* WCDBOptimizedSQLCipher-prefix.pch */, - F83AA16D87731A9D1F4DBD9B22E0F7B5 /* WCDBOptimizedSQLCipher-umbrella.h */, - 57112FF9C13E952D32767DE7E52A6998 /* WCDBOptimizedSQLCipher.debug.xcconfig */, - D05D3A4DC15E54B38CB174AB1707F02C /* WCDBOptimizedSQLCipher.release.xcconfig */, + CF30C677E32FA830E645F2C3BB0172B1 /* Core */, + 7E972BBD4D0CAB239B62B38A7CFE09A9 /* Support Files */, + 0E4E1A9219322C33F239A78C7F5E2F3B /* SwiftSupport */, ); - name = "Support Files"; - path = "../Target Support Files/WCDBOptimizedSQLCipher"; + name = FBSnapshotTestCase; + path = FBSnapshotTestCase; sourceTree = ""; }; - 04EAC8D749495199E4F4015EA568017A /* iOS */ = { + 09F4DFCA7B51F6578C440A3013934F1B /* Log */ = { isa = PBXGroup; children = ( - 523CBAB8CAF34468B5402904E418B901 /* Foundation.framework */, - E6FC37377401182941FFB20A1035A933 /* QuartzCore.framework */, - C3208D7D718A79BBC3B9384E32256F6A /* Security.framework */, - A892CB525DEAC1E1F53B41226E5AFC5E /* UIKit.framework */, - D28489E1C38C95EF1D07BF0CD0A85216 /* XCTest.framework */, + 0B7BCC990372646D3640A2DF459E49F3 /* LogCache.swift */, + 57E62D2D77DEED3B201DFDA0618E0E9D /* LogContainer.swift */, + 43E7CEB1D2A3A5C0DBB12BF8FC56CB8E /* LogItem.swift */, + F1D73F882F8E812397C7CC5B0A6618CD /* SafeDictionary.swift */, + 4C9DA5A2D5BD3067E4B62F006F3BCE6B /* SmartLog.swift */, ); - name = iOS; + name = Log; + path = SmartCodable/Classes/Log; sourceTree = ""; }; - 15FD889B319764E25F2C07EBB5840C58 /* Support Files */ = { + 0E4E1A9219322C33F239A78C7F5E2F3B /* SwiftSupport */ = { isa = PBXGroup; children = ( - 586CEF3C778B1CA10216855665336254 /* SnapKit.modulemap */, - 9DDA253A371800B761863D370EB8DA28 /* SnapKit-dummy.m */, - 343F3B1E09790572A6CAFAF95010B39C /* SnapKit-Info.plist */, - 9FA4DFB85B8BF5A18EDB74A8189262F5 /* SnapKit-prefix.pch */, - 1DF9DF1A9D97BEF7AF54F2FEFEE23AE0 /* SnapKit-umbrella.h */, - BC3729C5B5DB3FDFBE89ADB7BC30CFED /* SnapKit.debug.xcconfig */, - 4A957AEE9B28E0D13775629CCEB31E52 /* SnapKit.release.xcconfig */, + 992A16CABA4C83CBEACADDABDE5021A8 /* SwiftSupport.swift */, ); - name = "Support Files"; - path = "../Target Support Files/SnapKit"; + name = SwiftSupport; sourceTree = ""; }; 16C17349BA1B06E17DADE08F8DFF5502 /* Targets Support Files */ = { @@ -1227,789 +621,527 @@ name = "Targets Support Files"; sourceTree = ""; }; - 1FBE93D339BAC3963058FE11DE9AB77B /* Development Pods */ = { + 1EC73E5802EDCA8941212E2C0320FD68 /* Support Files */ = { isa = PBXGroup; children = ( - EA3357C6F6D23120B432667D8921CA9F /* SmartCodable */, + E30EB7375ADE85CDDB7E41CEAB4FB6D5 /* BTPrint.modulemap */, + 926AFEC77F93BCAD652BB781C5D0AA8C /* BTPrint-dummy.m */, + C4750BB7C125054792532A6CE7EFC1F8 /* BTPrint-Info.plist */, + 54E6DE8DDA000868195FED827A109AD1 /* BTPrint-prefix.pch */, + 6226D5547537E7D1F86B312E2F57D4F0 /* BTPrint-umbrella.h */, + 1EE51CB52688C6956C3806BE1352E6A1 /* BTPrint.debug.xcconfig */, + 12D66D4EBB5005BCB197AA15A08144D1 /* BTPrint.release.xcconfig */, ); - name = "Development Pods"; + name = "Support Files"; + path = "../Target Support Files/BTPrint"; sourceTree = ""; }; - 1FEAF6005DA9E3D6C191F38C3C3F8FEB /* Support Files */ = { + 31989EFDACEAF10A88E4456344A3CC68 /* Impl */ = { isa = PBXGroup; children = ( - 686713A2ADF7635E962053D7B5BCDE83 /* HandyJSON.modulemap */, - 4711916E7B6BC9EDCEB84C83D65ABE93 /* HandyJSON-dummy.m */, - DA345BD674D6C7F2AFDCCD4E5A6520B1 /* HandyJSON-Info.plist */, - AE6B62F1651CE843373519CDD60C5F25 /* HandyJSON-prefix.pch */, - 0110482CEAC61185104B0F2A20BFB4B6 /* HandyJSON-umbrella.h */, - 4032808F9DA898CCC05CA3A09966607E /* HandyJSON.debug.xcconfig */, - 9DD5BACBA6C6D7D9023F4EEAEF6AA63F /* HandyJSON.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/HandyJSON"; + C89E8087BFA786A66175CFC23BA8FF12 /* JSONDecoderImpl.swift */, + 91432EF00E1AB07F6B570628BF9725A7 /* JSONDecoderImpl+KeyedContainer.swift */, + C00DB4F15575B9722480D9D45738DD49 /* JSONDecoderImpl+SingleValueContainer.swift */, + 829E66367677D2B1D0128D6D228FD3A4 /* JSONDecoderImpl+UnkeyedContainer.swift */, + B5D179B728984FF882E8BF4096799056 /* JSONDecoderImpl+unwrap.swift */, + ); + name = Impl; + path = Impl; sourceTree = ""; }; - 2FBFB9D8E96026D735891CBFEF5A1070 /* Patcher */ = { + 31D698C122DAC16CE786204DDC7267E6 /* Products */ = { isa = PBXGroup; children = ( - D09AE90122BA076289207672D92C0950 /* Patcher.swift */, - 3237B54E492CA6E8870521CDD3F613BD /* Patcher+Provider.swift */, - 345703E7CF3B18DFA38742BF2DAD0EB3 /* Patcher+Transformer.swift */, + B66F7BC9A4DCD060099089C86B6DBC00 /* BTBubble */, + 63D6FCCD448B91FE5083D3C830B09E34 /* BTPrint */, + D9B8AA14A5BB1D0CE3A003CB6A566265 /* CleanJSON */, + 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase */, + CD54121DDA84872534168702B5F92950 /* HandyJSON */, + A4CFCEB2A58CA7A3CB15E26DD28CA8D6 /* Pods-SmartCodable_Example */, + 0B9662B4BE2283F2E38F7155D5266F8E /* Pods-SmartCodable_Tests */, + 3E623AAE662B463FDDE8B268BDEA3E7B /* SmartCodable */, + 979486118B3E90C08386079D57962701 /* SnapKit */, ); - name = Patcher; - path = Patcher; + name = Products; sourceTree = ""; }; - 304ACC37981D7EB0E25D351473306DF7 /* Core */ = { + 37704050BE514436D26A3EB63D42197C /* Support Files */ = { isa = PBXGroup; children = ( - EC222A9A63C304EB2AA02877164C9C90 /* FBSnapshotTestCase.h */, - 8D6B4B87B15CBF895D050929727FBC7F /* FBSnapshotTestCase.m */, - 1E5911145B436332EF43EBBDE7E6CDA9 /* FBSnapshotTestCasePlatform.h */, - 3D8462A4E4A62FFAA2EA934440DD042D /* FBSnapshotTestCasePlatform.m */, - 8944B5E835D69F7ACF99BAE48649B2BF /* FBSnapshotTestController.h */, - 3BCF255A8D93A5832ECBCCFD5006F2EA /* FBSnapshotTestController.m */, - 8CF972F529FCD52A4837EF7384E25630 /* UIApplication+StrictKeyWindow.h */, - D2B3E35A4BC256533E927EE1175DFF3E /* UIApplication+StrictKeyWindow.m */, - E9E6026DFD06EAF5D78CF289D189A4AB /* UIImage+Compare.h */, - 6655E8C804740DB2886BEC041DF12E7C /* UIImage+Compare.m */, - C01B5E0468FB391500B5CE91906AA1CA /* UIImage+Diff.h */, - 208BD4FE2601BA95A308D031441A72C3 /* UIImage+Diff.m */, - F6AEFAF46A1EB958A79BAB5E3AE57152 /* UIImage+Snapshot.h */, - BFA871D4B31BEA3D4DF3421A0453A0B6 /* UIImage+Snapshot.m */, + 019BF859EEBE1D8469A3CE37606A8760 /* HandyJSON.modulemap */, + 26D82883F952766DDE67EB5398B66E76 /* HandyJSON-dummy.m */, + FA5EA7509BA3790A709778D9D36944E7 /* HandyJSON-Info.plist */, + 2EBF008F9DBB55C9A18375B6B87D22A3 /* HandyJSON-prefix.pch */, + 91D961BD3D7E5A4FD5EFC37B4EF49FD4 /* HandyJSON-umbrella.h */, + 537BE90B32A5F1814137F702A3A820F6 /* HandyJSON.debug.xcconfig */, + 6CF935F6F0BF80B0C79325C2A66921C8 /* HandyJSON.release.xcconfig */, ); - name = Core; + name = "Support Files"; + path = "../Target Support Files/HandyJSON"; sourceTree = ""; }; - 36FD0FBF871F55DAE057D85527C93D6C /* BTPrint */ = { + 3F48FE6DFD3F4F7158F51E5CE37B2DDF /* JSONValue */ = { isa = PBXGroup; children = ( - DCE628DAB731CE9CF30F4A4CA4F2DD41 /* BTPrint.swift */, - FA773D1F7222071AA66218F4A74E3199 /* PrintFormat.swift */, - E888A1EE2825DA495FC34D225BF77FDB /* Support Files */, + F36F08B193D052643664F581E6D09590 /* JSONParser.swift */, + D0EEB810E2BEEE8D6FDAC45521E2B95A /* JSONValue.swift */, + 7AA1897EAAC2C936DF3C2195D9388328 /* JSONValue+Extension.swift */, ); - name = BTPrint; - path = BTPrint; + name = JSONValue; + path = SmartCodable/Classes/JSONValue; sourceTree = ""; }; - 586A854BCE5668A684B2847ACD79F494 /* JSONDecoder */ = { + 4261FFE260332A8857E6A48C5BD8E0CB /* HandyJSON */ = { isa = PBXGroup; children = ( - BE0B46342B4E52606B3A0416674B5552 /* Container */, - D59CBB92C7D1D94ECA4A9CFEDC13B442 /* Decoder */, - 2FBFB9D8E96026D735891CBFEF5A1070 /* Patcher */, + CDD07779AA8B42688ED0FF74BACC5AA5 /* AnyExtensions.swift */, + 93B6822011E346FDFA44C5A0CAB94482 /* BuiltInBasicType.swift */, + 7E920302DBA2124AFF869243E5CB6351 /* BuiltInBridgeType.swift */, + 390DC8D2A8DB0DAB9CA70268C2F74AF4 /* CBridge.swift */, + 7CB9011E862E377A63B0CA2058DCEB78 /* Configuration.swift */, + 796F5B9A676DF8041A953891F97BCA27 /* ContextDescriptorType.swift */, + ADDD58F0A7F5CBCD84256A572196E486 /* CustomDateFormatTransform.swift */, + BC6DB121D8A9523A91FDAB8376BE09FD /* DataTransform.swift */, + 76F616A528D452098E003EDF888C54AC /* DateFormatterTransform.swift */, + 0FD0E02013F60456068DC82258C06AB1 /* DateTransform.swift */, + 2E274A3EAC25DB6D5C25C3CBB604248B /* Deserializer.swift */, + C30DC42DFE9E9BEB719E4821761599C5 /* EnumTransform.swift */, + EC81D310210EE3584DF75E7C318F9318 /* EnumType.swift */, + 32B376CE8FE7B39265B74DCF06C524D2 /* Export.swift */, + 63337F29437FD6A05DCA6E50C4DF6945 /* ExtendCustomBasicType.swift */, + 1287F892FF63395DDABB49A2F8C39A3B /* ExtendCustomModelType.swift */, + 1ACD8767AB4E2B782160808FED94FADE /* FieldDescriptor.swift */, + 8D31C1D12C0D9C516CE738486208A159 /* HandyJSON.h */, + C4749570A46F497B425767CB4569ADF9 /* HelpingMapper.swift */, + 36F93E9634821D816540140F7E1D6199 /* HexColorTransform.swift */, + C57A6E8C38153E40B8497C02204DF7F4 /* ISO8601DateTransform.swift */, + 0965E60C4A8A6CB4CDB3FD2D5BF45433 /* Logger.swift */, + 6B6AE0B9AEB52789C2BA9C70151E337A /* MangledName.swift */, + 7D0C0E237F70C307DF23B940F50265F5 /* Measuable.swift */, + 7F1BBC050B82F2DBD3175EBCDBBAE1B6 /* Metadata.swift */, + FD9C9CD93F7F692FE8121F7F78EE6DB8 /* NSDecimalNumberTransform.swift */, + E7D0C8FFA3D3F1791A00D06DA9FB06C3 /* OtherExtension.swift */, + 9D5AD1AE1022A579A49D4DE848C3C5D9 /* PointerType.swift */, + 0600D0B09DB5802D6B378850043ADD4D /* Properties.swift */, + 2DCC7F0112605A85E8861B6A4E92D154 /* PropertyInfo.swift */, + BAF69AF530FDB1A1819B8E00A3E4775A /* ReflectionHelper.swift */, + 6FD01EC1237ED966BE6C99E868971093 /* Serializer.swift */, + 2852BF0E7B62CAF6AB4E994FD9DFF2DF /* Transformable.swift */, + 746BABF0910774EB502DC3C4F232413D /* TransformOf.swift */, + E20ABA9C7B9C59A9D3A5EA7AB0215871 /* TransformType.swift */, + 510325960A63C34B69B7173F76A69109 /* URLTransform.swift */, + 37704050BE514436D26A3EB63D42197C /* Support Files */, ); - name = JSONDecoder; - path = SmartCodable/Classes/JSONDecoder; + name = HandyJSON; + path = HandyJSON; sourceTree = ""; }; - 5EC6AFED8B4ED85257EE966F43F4A14F /* SwiftSupport */ = { + 47E83401A7A3D80C30C5C1DF7F4429F2 /* BTBubble */ = { isa = PBXGroup; children = ( - 6413BD32DD33B3C006539834A6029F46 /* SwiftSupport.swift */, + F09645CD0AE835FD6F2CC1C70F2768E6 /* BTBubble.swift */, + C236F0CDFBBFF56E8E482E41A943E19E /* BTBubble+Animation.swift */, + 319CD0A8663A00A572B4418C10FE8894 /* BTBubble+Check.swift */, + A8396A1DCA6FC67A7830D34F6F815289 /* BTBubble+Draw.swift */, + 4475151C4A7FB0660C3CDE88C6863EEF /* BTBubble+Location.swift */, + 02A4470686F2D00D08E538160531B64E /* BTBubble+Menu.swift */, + 666C02C1B42B0868B4A816FBD07E22A6 /* BTBubbleConfig.swift */, + EE7E7A774098C77B700C918B4B303354 /* BubbleTools.swift */, + 8589C51E960CB6893CA744448B6E7B26 /* Support Files */, ); - name = SwiftSupport; + name = BTBubble; + path = BTBubble; sourceTree = ""; }; - 64574C69C8EE6DD4B5AC15F28A5E6BB4 /* Support Files */ = { + 50F10E578FD38297123917C54A81025D /* Impl */ = { isa = PBXGroup; children = ( - 03BA22166A075933C743B2C9D1C85E9F /* SmartCodable.modulemap */, - FE71CAA940B03B2DDA72A6A70DA38BFC /* SmartCodable-dummy.m */, - 6DC7F8D1A909AADFB0E22BC9B1D3C7B4 /* SmartCodable-Info.plist */, - 672B415C1B19E7C0F422085F2399E7F0 /* SmartCodable-prefix.pch */, - 5B1200BCAF314037FF573D41166091D8 /* SmartCodable-umbrella.h */, - 87765750E33B18AE518B6F447E6C87ED /* SmartCodable.debug.xcconfig */, - 9E36FB803EEC5440AF34F62163B0EDD6 /* SmartCodable.release.xcconfig */, + B2E248320C9CBA206187879E5FDFE4C6 /* _SpecialTreatmentEncoder.swift */, + 995E5EF37D2EA75ADFF0B21D968E5B58 /* JSONEncoderImpl.swift */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/SmartCodable"; + name = Impl; + path = Impl; sourceTree = ""; }; - 6D9F0FF8A91DB73311F9BC21DAAD021C /* SQLiteRepairKit */ = { + 51E807718C6E5146100B75771DFC5191 /* SmartCodable */ = { isa = PBXGroup; children = ( - 6866EE8AA2F1FF8308B5C3410AEA8C40 /* SQLiteRepairKit.h */, - 9D577565B80212CC59E86358A09119B1 /* sqliterk.c */, - 5B9BEE2C0EC151B67961F46092A989DE /* sqliterk.h */, - EB44A0EAF3083A0C1BB831A625B3A464 /* sqliterk_api.c */, - 65031BFCAFB9694B1F3F528750789158 /* sqliterk_btree.c */, - 186D22B5F301661D7D43BA272978F548 /* sqliterk_btree.h */, - 9BC163C89756D7DD71745C9D0ED58162 /* sqliterk_column.c */, - A361C5D364F6A6DA615D350869696116 /* sqliterk_column.h */, - A2BA444A4E60E7EA50A97DCF8F4CC456 /* sqliterk_crypto.c */, - 43E555ABFE305E012A37237BC940803F /* sqliterk_crypto.h */, - A24DE9EEC0E48E6087452D0991A25DBB /* sqliterk_os.c */, - 6DCAC454A3B4DC896C97A76C0162F55F /* sqliterk_os.h */, - D36CFDC8FE52D5BF5257BBC8979DE5EC /* sqliterk_output.cpp */, - 5100DD0D061A6FC95142F30916FF35E1 /* sqliterk_pager.c */, - EFE265BEFD53265D1B57FD37F6C1C080 /* sqliterk_pager.h */, - B424B547BC415CB72334DBEE448A4DB1 /* sqliterk_util.c */, - F92DEA4DA3E1E8E57E1E048E7AD51789 /* sqliterk_util.h */, - 26F087E6B19DA0211F8B01B1D81F844C /* sqliterk_values.c */, - E3C3826A17E7079B5E9B8EF5E0726A8B /* sqliterk_values.h */, - B72D1EF63A1BD4F73D9350AAFA3A3D2F /* Support Files */, + 9B1FB30C0338F0FFA06BFCC6ED6E8EEE /* Cache */, + E407636689F088725517C5D0D8F9824C /* JSONDecoder */, + D0F4B0152FF9B0F5344FAF2C27139713 /* JSONEncoder */, + 3F48FE6DFD3F4F7158F51E5CE37B2DDF /* JSONValue */, + 09F4DFCA7B51F6578C440A3013934F1B /* Log */, + E58AF6FD854CFA3E8C95C4B2408DBD50 /* Pod */, + 9E08D8F8739D7EF5BE062758CF51F6E9 /* SmartCodable */, + 866B8F9B854657C57015129E41A31C64 /* SmartType */, + 6563CF7E170D3CE734DB0B7A96075769 /* Support Files */, + 7D0F1733AFDEE6B3B3E7D7B104F472B9 /* Transformer */, ); - name = SQLiteRepairKit; - path = SQLiteRepairKit; + name = SmartCodable; + path = ../..; sourceTree = ""; }; - 764CFBCD5A23460E02A7F5493C0A8D87 /* WCDB.swift */ = { + 6563CF7E170D3CE734DB0B7A96075769 /* Support Files */ = { isa = PBXGroup; children = ( - 7F3BEEE19C0A78E1A2CA95A33072BA36 /* Atomic.swift */, - 8E63D643A1B5C6A2B7C0A46448402CEB /* ChainCall.swift */, - 0A67D02E48C372F7F65EF8E90E5E4446 /* CodableType.swift */, - 052C76D3ECB08C7CE97A583A8F4AA784 /* CodingTableKey.swift */, - 080B01573DB252F29350F0BEB393D939 /* Column.swift */, - B49B1E6ADFC78844B1A8F500C06976E2 /* ColumnCodable.swift */, - 9E3A3F838435552834A4D0E6C267929F /* ColumnConstraintBinding.swift */, - 6900708CD940876C68B468F9E43E35B5 /* ColumnDef.swift */, - 215B5A8E4B87860917054FA268224A4A /* ColumnIndex.swift */, - 07024BD00FC36634A74C70568308AA01 /* ColumnResult.swift */, - C8053B0C2844CD59CE3E68D5FC9DDE5B /* ColumnType.swift */, - 2369A4FD37B12F6C5C3AD86835E5DCD9 /* ColumnTypeDecoder.swift */, - 00E1722C947F1DA1DF228499FC65654C /* CommonStatement.swift */, - 78CD18F607C4C7B3260A2086E6FA71F5 /* ConcurrentList.swift */, - 7B318245EAB932A9788ED4E4D8564AD0 /* Config.swift */, - 2C4935A7C5516AB70886A15F59CC104A /* Conflict.swift */, - 338B1D796753AF41826F3EC41206089D /* Convenience.swift */, - 194C0EE64ACC9E3E4B7814090F7A7E53 /* Convertible.swift */, - 15AA5C0185FEA92FCCC59356558DB25B /* Core.swift */, - 65BEC92F44B8431C10E16C69DE91C591 /* CoreStatement.swift */, - 9F616208225C5B42B50ABA5F5267C29F /* Database.swift */, - E871449A711764164F5DF40EE5109741 /* Declare.swift */, - FDC0F420686D5E03E5291BD62C6B6F99 /* Delete.swift */, - 8D8F51139F0FA15FEDE192F7F29A3781 /* Describable.swift */, - 9930E634CA9F9592BA112E4EA073572B /* Error.swift */, - 35874CD3E2284E8C73B3DF226CFAFE02 /* Expression.swift */, - 69EED8E214F52686EF00631CE13D11DA /* File.swift */, - 901AD1CA40244E43697CA8525620F3B2 /* ForeignKey.swift */, - 48E65E8527303A5A1758E602CBFD988D /* FundamentalValue.swift */, - 3E966EA41E66C041E21596A3772AADB3 /* Handle.swift */, - DA2AB63F2AC5AC4FBB2A1B85A3A1BB92 /* HandlePool.swift */, - 798614252B284BD86026E6391A1D6B83 /* HandleStatement.swift */, - 8F2E09890770921E19347954E8967E50 /* IndexBinding.swift */, - 189DDDBFF6D76C5E4E736A23810B2BFB /* Insert.swift */, - 7730B02FC8DBB419EF7E5DD4C7069878 /* Interface.swift */, - 1710B685152D86B0CBB66C7CFD397597 /* JoinClause.swift */, - F56261BCBCA2343ACB3164AE2B218462 /* LiteralValue.swift */, - 234332AF7FFA3F89DF56548B0498751F /* Lock.swift */, - C9D753BDFA887910415613027FC5070B /* Master.swift */, - BC50E104171DCA96B772A10AA0564122 /* ModuleArgument.swift */, - 3C8C2472E4FE52411D856291FE3408D2 /* MultiSelect.swift */, - CED8325151406ED11C82AF15BBFD7E6E /* Operable.swift */, - E07019FEB983E7289826370A121CFF96 /* Optional.swift */, - 83F45E6394093E1369C044D428C8879A /* Order.swift */, - C0578B106653292AA1BCD11BC78ECD48 /* OrderTerm.swift */, - 14E440614E76DBC6A5930D8F20B2042D /* Pragma.swift */, - 468DF5A09D8D79ADC328CC7F75D956AF /* Property.swift */, - 644177FA36D4B8A4E563D29BDA08DFA1 /* Recyclable.swift */, - 43FFE7610801F54DFCE0B7C42FE349DB /* RecyclableCore.swift */, - 7D02FC03949EB55EFDEB6BD91B376C88 /* Redirectable.swift */, - B1ECB4EFC6697075F43D35D69C0F6BCE /* RowSelect.swift */, - 84F8D67CFB1FB3199FB53CCFDA73794D /* RWLock.swift */, - BCADA2E9A3086D97A8BCB6A43D4E9D67 /* Select.swift */, - F16BCF96DA4A6F9BAA3D405212DD2906 /* Selectable.swift */, - 7B7110CEA112EBF2FC498D5380951730 /* SQLite-Bridging.c */, - 7D0587A335645BB79F0222497FF85E14 /* SQLite-Bridging.h */, - 1A8D1A79FED4B435F107DC9231BCFBF3 /* SQLite-Bridging.swift */, - BF1352FCE3039BCA9739C2333B9AA5EE /* Statement.swift */, - 37BE3C52BE9E38A8757F78EF0A1829CE /* StatementAlterTable.swift */, - F631CC802E2701AD6DEAB71A9B7134CB /* StatementAttach.swift */, - 0DDAA9762BFF90942F2F387B26557AA5 /* StatementCreateIndex.swift */, - 6CE9165B4A6C85359A6DCFB5752AF15C /* StatementCreateTable.swift */, - 5CA8D934CA4195CBB60E7B64B4F6938D /* StatementCreateVirtualTable.swift */, - FAF9A5EA944619747B64BF79AEFCAB71 /* StatementDelete.swift */, - 3C4FA0CCF2A2DA9C40F7751A1FA54192 /* StatementDetach.swift */, - 7FBD193AEDCC1BC474026921C4493237 /* StatementDropIndex.swift */, - 6BF26EB92D747312A7EFF6EB2BE276AC /* StatementDropTable.swift */, - E15E404E75C9D493CD986005D7C5E51F /* StatementExplain.swift */, - 50553FB57F080F1E987A3CD55DE922CB /* StatementInsert.swift */, - 8D3E80998BCA7EF85CC765918FD0D670 /* StatementPragma.swift */, - 57420310DABA9A536A9A0996B4DFFD11 /* StatementReindex.swift */, - 1AE97353C403B1B353D4887A7644E854 /* StatementRelease.swift */, - B20F883B8D4C68B3B3B7937CF3DA069D /* StatementRollback.swift */, - 1A9F59771C2F07940C3D3E1D3219BEB2 /* StatementSavepoint.swift */, - 7D90EB55E616E8CECBE8918EF6E09491 /* StatementSelect.swift */, - CEF047CA737FB19838BEC0244141C05B /* StatementTransaction.swift */, - 32588646583AF8336B91EA2A0FB6CD2A /* StatementUpdate.swift */, - ADAA91299769BD42F20D8F8CD7793220 /* StatementVacuum.swift */, - 30F209D4AE80852F7B2A473B433E6231 /* SteadyClock.swift */, - 30D613F035701597084E06D383FA66CB /* Subquery.swift */, - 7D936226781B9F30DC482374790455EF /* Table.swift */, - 4EB84981C58672F8E06A0D4AC94C3282 /* TableBinding.swift */, - 9AFCAB9E9753399E6A58D76D66B7B130 /* TableCodable.swift */, - 60954761F92EED9592A31A783EC3B05E /* TableConstraint.swift */, - BC0D345CD33B982912326FCB76C211C2 /* TableConstraintBinding.swift */, - A60871F481FE13AFE0AF788771BD15CE /* TableDecoder.swift */, - 282C9EF12770BB707851C8092FA502B1 /* TableEncoder.swift */, - 4F652B64AD7EA719869A9BB4E4D5B39A /* TableInterface.swift */, - F73913468036FE8ADDE2D7B47A50BB4C /* Tagged.swift */, - 8073B9C0CAD4D26D09EB8F8C618A816F /* ThreadLocal.swift */, - 0D67E5BBBE0B0CE733CE89F049DA3E12 /* TimedQueue.swift */, - 0BB4D815AD7FDFA7FE61D12B8DBB2534 /* Tokenize.swift */, - C88B551F69097A3D9A651BB19E4806AE /* Tracer.swift */, - 2B17CFDDAB4B7441B376FCCB678C499F /* Transaction.swift */, - 0B4C445819691E20C66A3B0C876E8F09 /* Update.swift */, - 0CCB1D63CBD4130578F32B453D318E7B /* VirtualTableBinding.swift */, - 589169F9BA6B76B8D7A16765B1135F63 /* WCDB-Bridging.h */, - 75DD762DA8418DC60C817DD56DC3E353 /* WCDBTokenize.swift */, - CA24048C64FF7CE0C82482E1B7F3D1AB /* Support Files */, + 3CE069FEDA7806D9F405C9CD00DEBC07 /* SmartCodable.modulemap */, + 9771EF69C497A5113339604D439DBD71 /* SmartCodable-dummy.m */, + A9389F909C87A9935163E0C9AF9629B5 /* SmartCodable-Info.plist */, + 2C93FB183FE769D1FC0CB904D2C557D6 /* SmartCodable-prefix.pch */, + F593D03921D2C6F913665801765ECADC /* SmartCodable-umbrella.h */, + ACA8ECF0DA97BC31739DBB05EDA01B23 /* SmartCodable.debug.xcconfig */, + 4A4DC161ED69D1B1A989E4A6912C7B9A /* SmartCodable.release.xcconfig */, ); - name = WCDB.swift; - path = WCDB.swift; + name = "Support Files"; + path = "Example/Pods/Target Support Files/SmartCodable"; sourceTree = ""; }; - 77081CEAFEE4370CAC49585F341C1D87 /* Support Files */ = { + 732A086ECC941D37A14E38C56E1A9B2A /* Development Pods */ = { isa = PBXGroup; children = ( - 472F55A319BA51293F698631D979AE4E /* BTBubble.modulemap */, - 97D90DEDEA77DAB3CC21506808D91533 /* BTBubble-dummy.m */, - 1F395FD9DAAC93BBEFF0485E5984DA3B /* BTBubble-Info.plist */, - 6B72E0611C67C73EA6510B95978F87CB /* BTBubble-prefix.pch */, - AC26795DE4514FE32D3094E1B9384FC6 /* BTBubble-umbrella.h */, - D9E3BCE9634968B8A180F21A6AD2D46D /* BTBubble.debug.xcconfig */, - 5D6F6281A81E9332BA17E1E5D6E7AE6D /* BTBubble.release.xcconfig */, + 51E807718C6E5146100B75771DFC5191 /* SmartCodable */, ); - name = "Support Files"; - path = "../Target Support Files/BTBubble"; + name = "Development Pods"; sourceTree = ""; }; - 8B44EA15B7C9A49401D67455A392E0B3 /* BTBubble */ = { + 7D0F1733AFDEE6B3B3E7D7B104F472B9 /* Transformer */ = { isa = PBXGroup; children = ( - 6BCD89A8AF7896E1C2C1B554E7A51E56 /* BTBubble.swift */, - 47AFB782E50452241E979C069CCE7C93 /* BTBubble+Animation.swift */, - B507A62DC4EBD3BB69182CD41E19AEDD /* BTBubble+Check.swift */, - C5CDB7508D26894D5B12C0A1D125803A /* BTBubble+Draw.swift */, - 4003C2B584F6E186819D97CEB2E63F46 /* BTBubble+Location.swift */, - C5DFE21D0BEE989AE9E8287E5BEE62A5 /* BTBubble+Menu.swift */, - DC652D711B63F8C1721F16CB2979AE0B /* BTBubbleConfig.swift */, - 848CD67E6D3721BE0AB072D0731ED981 /* BubbleTools.swift */, - 77081CEAFEE4370CAC49585F341C1D87 /* Support Files */, + 9FAB40FD80A45A7E3594DC159F7D54B6 /* ColorTransformer.swift */, + FE716DB85C8936F875B13305FA42C410 /* DataTransformer.swift */, + 8ADD33B297AB30B353CFB5D0A4234E39 /* DateTransformer.swift */, + A4FA9C2F58756A6AFCF914B64DC8959B /* Transformer.swift */, + 3A5490ABF50B6719BC634405F60AB3E6 /* URLTransformer.swift */, ); - name = BTBubble; - path = BTBubble; + name = Transformer; + path = SmartCodable/Classes/Transformer; sourceTree = ""; }; - 8B99E941704955E913B59A4D2AEEFA80 /* Support Files */ = { + 7E972BBD4D0CAB239B62B38A7CFE09A9 /* Support Files */ = { isa = PBXGroup; children = ( - 928E408AEF03BB6E25B32C26721E705A /* CleanJSON.modulemap */, - 298E9370B4A805049548CB01C7F08CF6 /* CleanJSON-dummy.m */, - A860A482AA0D4015362C409845AF6F34 /* CleanJSON-Info.plist */, - CC7C3FEF64C65495CFE6D7B9F95A1355 /* CleanJSON-prefix.pch */, - D8501160FCCFA343E417A66AA91DF92B /* CleanJSON-umbrella.h */, - 65425402E91EFABF55F0BF3523CE117D /* CleanJSON.debug.xcconfig */, - F5F4960C860E51A6192EB670A1528988 /* CleanJSON.release.xcconfig */, + DC816DCD26D7E20707BD2C4B66521329 /* FBSnapshotTestCase.modulemap */, + B9E9FCD5E63CE808B8773D040F1E2BA8 /* FBSnapshotTestCase-dummy.m */, + 25A597F47861F7BE3A2E02D5EC48740D /* FBSnapshotTestCase-Info.plist */, + F8C4BD4F4718E6FA4AC7DEA7CFD13293 /* FBSnapshotTestCase-prefix.pch */, + 7FF03B8E2DF800F666228FD3C0F9026B /* FBSnapshotTestCase-umbrella.h */, + 2565E609AC51A4E4FCA81F2594C690F6 /* FBSnapshotTestCase.debug.xcconfig */, + 3E6F38F38A655D1D2F8385D4A13D03BD /* FBSnapshotTestCase.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/CleanJSON"; + path = "../Target Support Files/FBSnapshotTestCase"; sourceTree = ""; }; - 8EB303108F4B4E4275CE95FED804AF48 /* Products */ = { + 8589C51E960CB6893CA744448B6E7B26 /* Support Files */ = { isa = PBXGroup; children = ( - B66F7BC9A4DCD060099089C86B6DBC00 /* BTBubble */, - 63D6FCCD448B91FE5083D3C830B09E34 /* BTPrint */, - D9B8AA14A5BB1D0CE3A003CB6A566265 /* CleanJSON */, - 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase */, - CD54121DDA84872534168702B5F92950 /* HandyJSON */, - A4CFCEB2A58CA7A3CB15E26DD28CA8D6 /* Pods-SmartCodable_Example */, - 0B9662B4BE2283F2E38F7155D5266F8E /* Pods-SmartCodable_Tests */, - 3E623AAE662B463FDDE8B268BDEA3E7B /* SmartCodable */, - 979486118B3E90C08386079D57962701 /* SnapKit */, - 5DCCF5B5F792D4EC76585F50AC7D8D7B /* SQLiteRepairKit */, - 3A669A12B69A63E0BEF5B0382A3A729B /* WCDB.swift */, - B3CF92365D6AE0F35C3602CF6C0872AE /* WCDBOptimizedSQLCipher */, + B884BE2A9A48EFA0DCB33348C5EECBCA /* BTBubble.modulemap */, + A77DB2179984C4C073E5FC6BDCD19B77 /* BTBubble-dummy.m */, + 274BB5419B8D40BD05519C560CFC077D /* BTBubble-Info.plist */, + 24562DC38CD0C27E5FCC2152077E3513 /* BTBubble-prefix.pch */, + 4CAE8816531C7030F85857D829CF295C /* BTBubble-umbrella.h */, + 4FD9F7D2497A25B05DF82AF7F12F84DF /* BTBubble.debug.xcconfig */, + D8123B10463E4148BBE847951CD834B0 /* BTBubble.release.xcconfig */, ); - name = Products; + name = "Support Files"; + path = "../Target Support Files/BTBubble"; sourceTree = ""; }; - 94416DF3087C68B20F2B70D8B0FF8380 /* Log */ = { + 866B8F9B854657C57015129E41A31C64 /* SmartType */ = { isa = PBXGroup; children = ( - 57205A5656AF71CC52D58B1C38172870 /* LogCache.swift */, - 242B3038A4DB16F77DDCEDDE83743BC5 /* LogContainer.swift */, - C9285283C0400C69E185F4F4E5C3699A /* LogItem.swift */, - EDF7058B96B59956D0341D5EE8DB387B /* SmartLog.swift */, + FAA37D00854B1424AE598ADE8E254D07 /* SmartAny.swift */, + 32C90D9D754077A7B4B1B5AC50059287 /* SmartCaseDefaultable.swift */, + E807ABEAA7D69B696DEF09C5E71FF4F5 /* SmartColor.swift */, ); - name = Log; - path = SmartCodable/Classes/Log; + name = SmartType; + path = SmartCodable/Classes/SmartType; sourceTree = ""; }; - 965E29F42E82F7FB2557FA7233FFFABF /* Support Files */ = { + 98C45354D057DFD460070868850871E7 /* Support Files */ = { isa = PBXGroup; children = ( - A517728630E48F320F0B505002BFD256 /* FBSnapshotTestCase.modulemap */, - C4C12BFAA6F02D6D9B0F42E75644DD5E /* FBSnapshotTestCase-dummy.m */, - 6EB49BA14169665C8D4821A83FD6E489 /* FBSnapshotTestCase-Info.plist */, - 9A09037802A20D832A880AA28340A8C1 /* FBSnapshotTestCase-prefix.pch */, - 314EE032EFE20CD4E06F74092A6C187D /* FBSnapshotTestCase-umbrella.h */, - DC8CB60731C501F663A8ABBBFBAC4FCC /* FBSnapshotTestCase.debug.xcconfig */, - 55309A18A8E224B31E20FF7DA75F1AE7 /* FBSnapshotTestCase.release.xcconfig */, + DCD54B400F0BA763829F393B36FC4C7F /* CleanJSON.modulemap */, + A370EE4D019ADFE65F2DC1FF9EDBA187 /* CleanJSON-dummy.m */, + 56F3BDAC789DF61F2D9350035669FEE3 /* CleanJSON-Info.plist */, + EEAB8D6BB2A7369CCEF3D49B4BB21A9D /* CleanJSON-prefix.pch */, + C6D3430E32742C8A84D354226C873C6C /* CleanJSON-umbrella.h */, + 0F6C61A3718CAD5B727FA89E9A50D662 /* CleanJSON.debug.xcconfig */, + C548E3997850B2E10E6E8D21CACB81A3 /* CleanJSON.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/FBSnapshotTestCase"; + path = "../Target Support Files/CleanJSON"; sourceTree = ""; }; - 9B454AC6DCC799DFAAA4F9D0A9E9F162 /* FBSnapshotTestCase */ = { + 9B1FB30C0338F0FFA06BFCC6ED6E8EEE /* Cache */ = { isa = PBXGroup; children = ( - 304ACC37981D7EB0E25D351473306DF7 /* Core */, - 965E29F42E82F7FB2557FA7233FFFABF /* Support Files */, - 5EC6AFED8B4ED85257EE966F43F4A14F /* SwiftSupport */, + 2B7CFF9C9E99F6CB429445432536C7C2 /* Cachable.swift */, ); - name = FBSnapshotTestCase; - path = FBSnapshotTestCase; + name = Cache; + path = SmartCodable/Classes/Cache; sourceTree = ""; }; - A93430075622BC499DDD84AF86C0FC1F /* WCDBOptimizedSQLCipher */ = { + 9E08D8F8739D7EF5BE062758CF51F6E9 /* SmartCodable */ = { isa = PBXGroup; children = ( - 7B59B3059BFCFF25377D0910E7F11C89 /* alter.c */, - 2640505E1669FA0E4615AB6C2A07EACF /* analyze.c */, - E554DEBB8837193A575EA37F69484063 /* attach.c */, - 3DA5B0BB29BEE655E198C29614913C2A /* auth.c */, - 2FACBD8B689AF9C3F28B0EE67CE6F169 /* backup.c */, - 67862AEB121CDDE6370187F66B07A7EF /* bitvec.c */, - 4C3A6680786E7AEEAEBF6ACBC7F46634 /* btmutex.c */, - 981FC3D828F7DDCD2F77A0BF2CEB5313 /* btree.c */, - AF7E6F369E3B04273EEA3F174700C2E0 /* btree.h */, - F77B4DD50B4E2BA5873C6AB52E4A8664 /* btreeInt.h */, - 46611858B8325FB36AD0D5F498366D03 /* build.c */, - 9F8BF617506C58E3EDF6131E3780534E /* callback.c */, - 1EF0B53B69337F7F4AA44D3A9F9CDE37 /* complete.c */, - 9D5E5FF169696273D350DDAD938BA59C /* crypto.c */, - C0CCC34D442A08D6E9FEECCD26D1E3B7 /* crypto.h */, - 06654512231B9F787D6A5363A3BB410D /* crypto_cc.c */, - 248FD8535E726D670FA271336DD6BD81 /* crypto_impl.c */, - 6FFB72C4FC2D499DF9218B70627E31C1 /* crypto_libtomcrypt.c */, - 1D697FCDF8A877E72AE4E548CE2110DE /* ctime.c */, - 4A21FD23B7B9D638D2D6437D1FCEEB48 /* date.c */, - 30204FFE690A0B9592706A78093E1503 /* dbstat.c */, - 81DB024EC9AFF73AA4502F4734CA810C /* delete.c */, - E4AF1DDFA0BFD4D141DC95A23E60E21E /* expr.c */, - EC9FF687080036A8654DA415051A4F52 /* fault.c */, - 1E5130A0E082DB74881AC7C0818F8965 /* fkey.c */, - 20EFA042731FA1BB8CE1D3B3CA1DB012 /* fts3.c */, - 0B13703C34892E109DC262AD9E026413 /* fts3.h */, - E5C698A33CA71DF66125CB48E115C9D1 /* fts3_aux.c */, - C63C50EBF0AE1A7E3E83D4462CD73A8D /* fts3_expr.c */, - CFCDD063DFADDF236ABB25163EB4A195 /* fts3_hash.c */, - 2F05955F92891DDC9863B462D73A04E5 /* fts3_hash.h */, - 820888330A2D426AAA53548B20928AC6 /* fts3_icu.c */, - 73713A6806AC55107EA83D93F777C0A5 /* fts3_porter.c */, - 446B401C0DD4B21F9A9BF00840223ED9 /* fts3_snippet.c */, - A1BE8BC5AD3696828942B96191FFC93B /* fts3_tokenize_vtab.c */, - EC269ED89F5E95338D486A4341D130E3 /* fts3_tokenizer.c */, - A343A2044144CB7474985FA357554BD0 /* fts3_tokenizer.h */, - FDC31AE155953A80BB668497C4AC2BA0 /* fts3_tokenizer1.c */, - 153C1F6555FA7C044BD0F0CC4C375069 /* fts3_unicode.c */, - 2ACC1B7946BEDD0237B5D92F1A9EF9F3 /* fts3_unicode2.c */, - 940A8C6613C7BC0BF47F245097A1BCAC /* fts3_write.c */, - 3F14A4BF349F40CAAB558A775EABD9D1 /* fts3Int.h */, - 51A93FC1E25AF66C3E9C18D8296E36B9 /* fts5.c */, - 6828855C8EB1DC703DFC765E3C8E9A27 /* fts5.h */, - EB6F7BA0DB362E9C44D65D67B447711D /* func.c */, - CC539335DC60778548E801CDB7F2D02F /* global.c */, - 18D88FE24C75AD053966BC639186BD5D /* hash.c */, - B6FD93E2638B8D26614D584022725EA7 /* hash.h */, - 6D070A8985C735AB5F1CA1940115E588 /* hwtime.h */, - D576389A8088EF7132E5C2014B4EE239 /* icu.c */, - 40AFCC5DF480085E54766074710BC33F /* insert.c */, - 2995ACAFEB77466B338AF49949E0F10C /* keywordhash.h */, - F63E4EB6FB734F947641DABA8C75AF07 /* legacy.c */, - D987A5E4DDCE06D16CADF70907060EC5 /* loadext.c */, - 8A6BBDBDEEF349AAA722FA356CBA7BD9 /* main.c */, - 3A5736E278A439A4F84876664433AD19 /* malloc.c */, - 611CDA25837467E463F32A67A9EF9FF6 /* mem0.c */, - 04AF682E0F5A9200126922C904DB3A17 /* mem1.c */, - 02F1F533ACB6C749844E6C51143FD7CC /* mem2.c */, - B879FC7FFD1918AD9A99D212BB3DA7FB /* mem3.c */, - 4456F7D1572273D7A8579F5AC4D14E2B /* mem5.c */, - 9150B5DCEC6DD38F143FBDEE388906CE /* memjournal.c */, - 4C7A0EFE15E507C964CE79BE8AC57D92 /* msvc.h */, - 5750120103B02747856DF9A69B4BCC83 /* mutex.c */, - 73B5134C3B0D0DCBF20DA94AC4C405B7 /* mutex.h */, - 8E60F4510824A7A8EADD930362F84E30 /* mutex_noop.c */, - 2BD0F700A73E13AE67151D1323421415 /* mutex_unix.c */, - D902F67F84D016160BC9C30B93A8F564 /* mutex_wcdb.c */, - B0F6A82607269E6FB6F472F6C4488DA3 /* mutex_wcdb.h */, - 959A3546F4262DC0138394886AA3D28D /* notify.c */, - 58EA21B6E71EBB420FCB0D177FFC3B0A /* opcodes.c */, - 014B1C0CEA4BF05C07C0E27BA426D4DA /* opcodes.h */, - 2E56852052AF5A2DCBC105963F8669A3 /* os.c */, - E4CAFE90E23A817910BA25BDC1390D64 /* os.h */, - F4A523DD234E18A60AF35F11CB72F42B /* os_common.h */, - 36E64B194309465F02BCBBB4DFC42F58 /* os_setup.h */, - D02525015C11C983A716B56C77A390BA /* os_unix.c */, - 6A335F1EDB942166F2779121CE29E585 /* os_wcdb.c */, - 00FE0A814FC0CF97A87C4BF7AE3C52EE /* os_wcdb.h */, - C0E5DF2BD31809E3F1A4018A2E009037 /* pager.c */, - 81A6B148540C158469908690D628A9BF /* pager.h */, - 7095CF12D4A8623FA91F06BD720560B8 /* parse.c */, - 33A1FC38E885F6CAA0517719FCC0A1B7 /* parse.h */, - 0138F7570768B19CEE6F7AB7AE7D1841 /* pcache.c */, - 7867ADA3ACBECE3FE0964EB6C2ADF7D6 /* pcache.h */, - 0FDC79FFAFD807358086B52EA83BF2AB /* pcache1.c */, - 0E157DD40B43D7133F4386E4833E41D3 /* pragma.c */, - A4D0796E3D77462A2F42DF4FD9C5BCF3 /* pragma.h */, - C6BABF528CFB1403AB76736DC9D8A507 /* prepare.c */, - 72E993CD880CBB3208C2A588FB128358 /* printf.c */, - 8DA4771CF91F3004D3D65B79990DE177 /* queue.c */, - 20BCCD509CA9B3F4E19F0B89D1F0DA9E /* queue.h */, - CE826E7F05CF3F8586C677CB5A2530B5 /* random.c */, - 2083F64F2D96303B570E6175B352347C /* resolve.c */, - A352B8E7226498116372CB1AD0618F54 /* rowset.c */, - 0D2C261220137389577E0E25D9696F66 /* rtree.c */, - 6D0D80684CB2A17DDA87A11515761E6D /* rtree.h */, - 15854FC71FC55631BB77E2D925160F40 /* select.c */, - 208CAEC6673B7C0C55E8A260CA2E9936 /* sqlcipher.h */, - A0752EA93024C04D691ED9C4C27314C9 /* sqlite3.h */, - 6A19D339940591628408D7B9957A84CF /* sqlite3ext.h */, - CF59ACCBC088180B9DDF32F0F236A4E3 /* sqlite3rbu.c */, - 82C013A66AAE87D26F22C959065F6D3B /* sqlite3rbu.h */, - 561BF226C66CCB775EEEF0E42F3E87BA /* sqlite3rtree.h */, - C14D61C7AE59E97D0F73C27659D8489D /* sqlite3userauth.h */, - 944178E3D8552FB8678D163FCDF781F4 /* sqliteicu.h */, - B85B1B1333F12E9C10C98F336EB35B05 /* sqliteInt.h */, - 2BAF3FD2C70B49834F7EC00332581CE7 /* sqliteLimit.h */, - 35E2F9F18CD38FADE9FBDBA79C2036A5 /* status.c */, - 59E469590BC9F29B51275D3ED6913071 /* table.c */, - 40A09FC531CEBD255071D71F9AA1FD3C /* threads.c */, - 325544FCE455196B6F391EE9FFEE5DD0 /* tokenize.c */, - E24C10B99ADAD73E210FB8245ED8197B /* treeview.c */, - 0D452F86E76CB24DF6ECA35D83AA8248 /* trigger.c */, - 79255177DD8C05F8B7066A72ADC29525 /* update.c */, - 06748A1A350AAD18055FC22AD20BBB46 /* upsert.c */, - AD44D95A3B0AA90BECF82F884FAA3C5A /* userauth.c */, - 4A64B6A3CDB35FD693AE7CC214BED1B7 /* utf.c */, - A17FFA6423420CF5D2CD5A85C44E4F88 /* util.c */, - 953E4CFA5CA8CCBA3E6CA55F7CFF2BD8 /* vacuum.c */, - 5283B716A76A18C9B408E0035F555B6B /* vdbe.c */, - 16FAB580F3341857A02C000870F30103 /* vdbe.h */, - E690F4F3A52E7BD1C7B5AEF2B5DA6211 /* vdbeapi.c */, - 36BB093C85AFBFBE00809739200019A5 /* vdbeaux.c */, - 4886E29175151E6108F75868065ABBF4 /* vdbeblob.c */, - 665EF7716439F0B62542010899E7BC02 /* vdbeInt.h */, - 27C5818B69BFD80E9CD7AB0525DF22C2 /* vdbemem.c */, - F726DF8A247CF9E3ED50B8EAA5957CFF /* vdbesort.c */, - 4A66148DE9C1A94AD684B306C4A2F0C6 /* vdbetrace.c */, - B753815544AFD5C6E0EBECDBE87DF183 /* vtab.c */, - E5B4B1A682E2866B6A4A07E9208DAA3C /* vxworks.h */, - 6FAA1DBD66A24E9AC890DC3D6119D2ED /* wal.c */, - D54143E7A4BC63635B0089DB6810A04A /* wal.h */, - F6A8B52AB6EF90B11566E30055201070 /* walker.c */, - 2AD26611F62EC841B8AA65D6D377987B /* where.c */, - 5198AB42A90C8765E2052D192FC434CD /* wherecode.c */, - 4CF668240903ACFCD31E3E022039B6E6 /* whereexpr.c */, - 3D41F501030CAB0211BB226AD82F40E6 /* whereInt.h */, - 27E0C82161F76C3621B9957E27ECF4E4 /* window.c */, - 00F973FF64003D3142BC9125D9FBBB09 /* Support Files */, + 55017ACE8DE4C20B38E0C7802356E9C6 /* SmartCodable.swift */, + B17DBF7CBD3616A875D3281F35287EA6 /* SmartDecodable.swift */, + 64E44B798553A3E18727230F8D89E3F9 /* SmartEncodable.swift */, + 6BAACBE9FC72DF06355302EE7B3A730E /* SmartUpdater.swift */, ); - name = WCDBOptimizedSQLCipher; - path = WCDBOptimizedSQLCipher; + name = SmartCodable; + path = SmartCodable/Classes/SmartCodable; sourceTree = ""; }; - B72D1EF63A1BD4F73D9350AAFA3A3D2F /* Support Files */ = { + BA4F31F07263C99FC76E66D632A59F09 /* Frameworks */ = { isa = PBXGroup; children = ( - AA051B6194661AA53CBD57DF37336F10 /* SQLiteRepairKit.modulemap */, - 0986BCD62FBDFF356818F2240DB86644 /* SQLiteRepairKit-dummy.m */, - 3726384DD45BD42064D3422F0CCB9D9F /* SQLiteRepairKit-Info.plist */, - AAF31A29B5ABB6F160DFCBA5CB8E203F /* SQLiteRepairKit-prefix.pch */, - ED36361B8D8564C73918F7F46E942300 /* SQLiteRepairKit-umbrella.h */, - 370B85F293D8CDDA899A559DE09A8A3E /* SQLiteRepairKit.debug.xcconfig */, - 47CA9F565D77284A1A541E3C884B8D9D /* SQLiteRepairKit.release.xcconfig */, + FB2668559AE577E6E8078C0C291AD417 /* iOS */, ); - name = "Support Files"; - path = "../Target Support Files/SQLiteRepairKit"; + name = Frameworks; sourceTree = ""; }; - B94D7768568A9992200DB461E8CF687F /* Frameworks */ = { + C00BDBDD99AEB786E744B3445CBC66DD /* Decoder */ = { isa = PBXGroup; children = ( - 04EAC8D749495199E4F4015EA568017A /* iOS */, + 7FFEEBFE7C3F6CA97EC2C91D3BF3AA9B /* DecodingCache.swift */, + 95214B05E868BF779E006FD88F1F0B9D /* DecodingError+Extension.swift */, + 037188BAD3B6E3D97703822C3762791B /* IgnoredKey.swift */, + A0442ACE2BA5F7E00E86DA7955E7AF77 /* KeysMapper.swift */, + B4E9A27193AA9BC77F718F28EA0E1B65 /* SmartJSONDecoder.swift */, + ADD1B40612B0CE612E816E472F043F2F /* SmartKeyDecodingStrategy.swift */, + 31989EFDACEAF10A88E4456344A3CC68 /* Impl */, ); - name = Frameworks; + name = Decoder; + path = Decoder; sourceTree = ""; }; - BCFDD7DCD36ED406EDDD79DCCFC876B4 /* Pod */ = { + CCE6F2769C982E839E4E6CB9D554361C /* Pods-SmartCodable_Example */ = { isa = PBXGroup; children = ( - 748AE91ABED537A2DF9E1BD4D1BD1216 /* LICENSE */, - 712F259C7D5BEFCEDDBE627A309BD417 /* README-EN.md */, - 08B65986CEFE01B5D27D34B5B6DC285E /* SmartCodable.podspec */, + 4B882D619BB4F3DBCA3958CF51481D0F /* Pods-SmartCodable_Example.modulemap */, + 85D2CD4F67092C56E310282E114ADE5B /* Pods-SmartCodable_Example-acknowledgements.markdown */, + 5D1C54C47A2FE062765D133366160F7F /* Pods-SmartCodable_Example-acknowledgements.plist */, + 9AB62CDC1D9A84669428234D73C264AF /* Pods-SmartCodable_Example-dummy.m */, + 767825513CDDC33C98AB0A7A3C9681D4 /* Pods-SmartCodable_Example-frameworks.sh */, + 70EF9FF8800B0AA22F5E4FE76FECA8D7 /* Pods-SmartCodable_Example-Info.plist */, + 6021C11E2C3E5FCDE30179E13E0E6452 /* Pods-SmartCodable_Example-umbrella.h */, + CF572B5B26ACF0A775C07589992A5507 /* Pods-SmartCodable_Example.debug.xcconfig */, + 6170F13C22D7194151A678E232C31D12 /* Pods-SmartCodable_Example.release.xcconfig */, ); - name = Pod; + name = "Pods-SmartCodable_Example"; + path = "Target Support Files/Pods-SmartCodable_Example"; sourceTree = ""; }; - BE0B46342B4E52606B3A0416674B5552 /* Container */ = { + CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( - 53D77D9C85C14C7889D991953799A90D /* _SmartJSONDecoder+SingleValueDecodingContainer.swift */, - 4D9E45948CEF9BF9077D26412102B6F9 /* DecodingError+Extension.swift */, - E78CA67C1117E52EF3FC13EB351A6819 /* DecodingProcessCoordinator.swift */, - 2DDE2047CA2148A5644CFD3E9B61B0C7 /* SmartCodingKey.swift */, - F628734F4AD8AC92C14058127679E7F3 /* SmartJSONKeyedDecodingContainer.swift */, - 11FBCD4D36359C93A5A40BC3BDEF2CD0 /* SmartJSONKeyedDecodingContainer+decode.swift */, - 04943FF1F9F4BCCF3A02297282CCAF6E /* SmartJSONKeyedDecodingContainer+decodeIfPresent.swift */, - 8153927F031D060140C06D57CFC4A431 /* SmartSONUnkeyedDecodingContainer.swift */, - FCEDA3C22B4FE876F9B1AE3E0300A4C9 /* SmartSONUnkeyedDecodingContainer+decode.swift */, + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 732A086ECC941D37A14E38C56E1A9B2A /* Development Pods */, + BA4F31F07263C99FC76E66D632A59F09 /* Frameworks */, + FDCBEBF5E487956EF93414AE43BD350B /* Pods */, + 31D698C122DAC16CE786204DDC7267E6 /* Products */, + 16C17349BA1B06E17DADE08F8DFF5502 /* Targets Support Files */, ); - name = Container; - path = Container; sourceTree = ""; }; - C1448073401A9D7F9DE97B99C35D77FD /* HandyJSON */ = { + CF30C677E32FA830E645F2C3BB0172B1 /* Core */ = { isa = PBXGroup; children = ( - BBC9E37E1231F7C47C1FF217714CB44C /* AnyExtensions.swift */, - C85D39B63CA259934A33F2B43CA2305E /* BuiltInBasicType.swift */, - 8FFCB8A3A3DABA88D9B4E1ADB6B2BC15 /* BuiltInBridgeType.swift */, - 39158D4DDE62D27C5D0AEEDEBE7271D1 /* CBridge.swift */, - DDB2EB56477F0F500E5E6BC9306CD760 /* Configuration.swift */, - CEA6C3D31D4A4A55C19A9EA22E0F3C2A /* ContextDescriptorType.swift */, - EF792627DE1714E38E8A9B2C7DA6A6B2 /* CustomDateFormatTransform.swift */, - C54DA92E53C8E33D0D0C63CDF41C84CF /* DataTransform.swift */, - A4EB0C0E105B37698E256E0C139E5B82 /* DateFormatterTransform.swift */, - D07518FFD2D8665D6174ADB9E47C25D2 /* DateTransform.swift */, - BE9E2E9B8EEBD6E444845703ABB17FA8 /* Deserializer.swift */, - 14C767AB16373063799E33054D23146A /* EnumTransform.swift */, - 15335B1C99316156D53EFB132C72D90B /* EnumType.swift */, - 5BEE5FD64126C65AE637CAF7B4E236D6 /* Export.swift */, - 57D9A0F7AD288FBCB187DF9CCC042E97 /* ExtendCustomBasicType.swift */, - C3C2131D87E7F2B2C1601DBFDB5E83BD /* ExtendCustomModelType.swift */, - A4CC74704F393D76FD2165D29F8C4069 /* FieldDescriptor.swift */, - 7009D451088814BE5B398BCC801037CB /* HandyJSON.h */, - 08951D687428D680F5A7D8AA9B6859F5 /* HelpingMapper.swift */, - 345CF363ECE5628BDA0E1001B5661B0F /* HexColorTransform.swift */, - CCAC6A3BDBBBA93A2573EDA5CD4CB7FB /* ISO8601DateTransform.swift */, - 11E4EA8972278437BFB8CED63ECCD00D /* Logger.swift */, - C177859E1A60F619FF28EED9334F6BFC /* MangledName.swift */, - 30725197DB5D704DA8C15608B3F3AC42 /* Measuable.swift */, - 6D4268C0E94A4D1CEA5A9AFA2C42E291 /* Metadata.swift */, - 4C6B2412CFDC619866F34C07873D2D08 /* NSDecimalNumberTransform.swift */, - 40DE48CED81F4007A52E53CD61D79161 /* OtherExtension.swift */, - A7758FB3B629E7C38E290756F49F3101 /* PointerType.swift */, - 0AE978CDB4DB8CE29F1012CDCB29CDE7 /* Properties.swift */, - 782FEEC464789BBF3AB2DEDD778C2B0A /* PropertyInfo.swift */, - D6C3547D57598A7565784581664A1EB4 /* ReflectionHelper.swift */, - 007BA55F5D4490BD94C8451E76A00455 /* Serializer.swift */, - 074E54E9F3324F34290CCDEE383AE984 /* Transformable.swift */, - C8D5FA619E1FFE76299F63EA49B6497C /* TransformOf.swift */, - 957AD6E6B2DEA9C2223DBD3581F63EBC /* TransformType.swift */, - C1662A646B256DAAC436E92852D15012 /* URLTransform.swift */, - 1FEAF6005DA9E3D6C191F38C3C3F8FEB /* Support Files */, + 20BC59163CF72AADA6459ADA846EBF1F /* FBSnapshotTestCase.h */, + A11B531AF457EC4F99F06F115FDE0A45 /* FBSnapshotTestCase.m */, + 87EF2DCAFAACA539DB4A58A75FC36303 /* FBSnapshotTestCasePlatform.h */, + B3CC75B7FCBD0A88F04962B84E46D054 /* FBSnapshotTestCasePlatform.m */, + 4A29F6A0D45AF40A67824A0487C3A989 /* FBSnapshotTestController.h */, + 2CAD959505600831AE1B1760854D7178 /* FBSnapshotTestController.m */, + 233DAEDE45A5CF0A47B6462C8C9F92B4 /* UIApplication+StrictKeyWindow.h */, + 87C56FECBDEE19803E1748DE1C16FBBA /* UIApplication+StrictKeyWindow.m */, + 60E0A4F5EA0780653EDE0A8F48FE2B14 /* UIImage+Compare.h */, + C5688C4B8AAD0B0302EE6D8567AB0A03 /* UIImage+Compare.m */, + D283527F80A00FBB2FF5776A4E3B27B2 /* UIImage+Diff.h */, + 209CC75BF3B9E4EF12E2CCE8787F9095 /* UIImage+Diff.m */, + 60B0F726C42000735EC1B76226554746 /* UIImage+Snapshot.h */, + 02B734C740F66C4CA7D3E58A2E3A71ED /* UIImage+Snapshot.m */, ); - name = HandyJSON; - path = HandyJSON; + name = Core; sourceTree = ""; }; - C4E32CAEB27EC1CA6AA0E99359E38370 /* Pods */ = { + D0F4B0152FF9B0F5344FAF2C27139713 /* JSONEncoder */ = { isa = PBXGroup; children = ( - 8B44EA15B7C9A49401D67455A392E0B3 /* BTBubble */, - 36FD0FBF871F55DAE057D85527C93D6C /* BTPrint */, - D0F9D9049AB85A6F36C4FFE5555DCD5F /* CleanJSON */, - 9B454AC6DCC799DFAAA4F9D0A9E9F162 /* FBSnapshotTestCase */, - C1448073401A9D7F9DE97B99C35D77FD /* HandyJSON */, - F56461ADED17BDA1F85D7260A92CD90D /* SnapKit */, - 6D9F0FF8A91DB73311F9BC21DAAD021C /* SQLiteRepairKit */, - 764CFBCD5A23460E02A7F5493C0A8D87 /* WCDB.swift */, - A93430075622BC499DDD84AF86C0FC1F /* WCDBOptimizedSQLCipher */, - ); - name = Pods; + 8F3DB64808585AF7EC48453CC5E40015 /* EncodingCache.swift */, + 61B5EAF366B8557B8062A765F73500C2 /* JSONFuture.swift */, + B1A452E1BB4D2E97E82928F4C874C8C1 /* SmartJSONEncoder.swift */, + E4D8ED149F3D4662ACD8B9384FC69FBC /* Container */, + 50F10E578FD38297123917C54A81025D /* Impl */, + ); + name = JSONEncoder; + path = SmartCodable/Classes/JSONEncoder; sourceTree = ""; }; - CA24048C64FF7CE0C82482E1B7F3D1AB /* Support Files */ = { + D5089C05AA8DF4AEE19DA89A217C7CD8 /* Support Files */ = { isa = PBXGroup; children = ( - B4AE57587CB01377DE7465D672246876 /* WCDB.swift.modulemap */, - 925381DED7E88D2040106861CAEFE6C8 /* WCDB.swift-dummy.m */, - 9EEBBB487C8AE88B5512D2789CC3EBB5 /* WCDB.swift-Info.plist */, - 40AB6BB3402A8F58BEB7A3B4C06CB9C2 /* WCDB.swift-prefix.pch */, - 593175FB6C4DDBC7DBC7DAE352763FC2 /* WCDB.swift-umbrella.h */, - 4EAA4EAE56C6CAB52B38138385B834F9 /* WCDB.swift.debug.xcconfig */, - 8D7BA7EC0C7015514C5CC8ECA03C5A70 /* WCDB.swift.release.xcconfig */, + 3A10F19A7083CCBB70471917A1BD6C04 /* SnapKit.modulemap */, + 89305DC7AA8CF17C4DFF5582FDC4E381 /* SnapKit-dummy.m */, + FF1E4A64EAB2DB18EB9CAD95399FE5C9 /* SnapKit-Info.plist */, + C2C99A53F71055734332736B13A49C28 /* SnapKit-prefix.pch */, + 96FC33890F5B9F948392563B47A573A0 /* SnapKit-umbrella.h */, + 0EE11E0147F987FD843DF343F4BEF9C5 /* SnapKit.debug.xcconfig */, + F9693744257055D6E8D886301B98967F /* SnapKit.release.xcconfig */, ); name = "Support Files"; - path = "../Target Support Files/WCDB.swift"; + path = "../Target Support Files/SnapKit"; sourceTree = ""; }; - CCE6F2769C982E839E4E6CB9D554361C /* Pods-SmartCodable_Example */ = { + E0646F01706B42305D43ED181AB83900 /* SnapKit */ = { isa = PBXGroup; children = ( - 4B882D619BB4F3DBCA3958CF51481D0F /* Pods-SmartCodable_Example.modulemap */, - 85D2CD4F67092C56E310282E114ADE5B /* Pods-SmartCodable_Example-acknowledgements.markdown */, - 5D1C54C47A2FE062765D133366160F7F /* Pods-SmartCodable_Example-acknowledgements.plist */, - 9AB62CDC1D9A84669428234D73C264AF /* Pods-SmartCodable_Example-dummy.m */, - 767825513CDDC33C98AB0A7A3C9681D4 /* Pods-SmartCodable_Example-frameworks.sh */, - 70EF9FF8800B0AA22F5E4FE76FECA8D7 /* Pods-SmartCodable_Example-Info.plist */, - 6021C11E2C3E5FCDE30179E13E0E6452 /* Pods-SmartCodable_Example-umbrella.h */, - CF572B5B26ACF0A775C07589992A5507 /* Pods-SmartCodable_Example.debug.xcconfig */, - 6170F13C22D7194151A678E232C31D12 /* Pods-SmartCodable_Example.release.xcconfig */, + DD91016CD3E4DB108E6B6B782539B2EC /* Constraint.swift */, + F3DD3A510DCBD287B46973C5625A7FB1 /* ConstraintAttributes.swift */, + 077FF679DE0A788D695D32FCF72B1002 /* ConstraintConfig.swift */, + 7D588A73906F98B13FC731364A9247E2 /* ConstraintConstantTarget.swift */, + 7570803E9622B6523B3325B01B79E44B /* ConstraintDescription.swift */, + 3803A342F79D0DBAEE0150E93A6B807B /* ConstraintDirectionalInsets.swift */, + C53C2DBE2FECF12DA6C33264A027EC82 /* ConstraintDirectionalInsetTarget.swift */, + DDEF3ACF04599EB1C214870D993C7153 /* ConstraintDSL.swift */, + 45DCF5151BEFE9D3018AFB99FE8F580F /* ConstraintInsets.swift */, + 30C72CEDB9E9899CABE8976D237E6C74 /* ConstraintInsetTarget.swift */, + 05DE8DDCC94E79120DAB11B9DBD24069 /* ConstraintItem.swift */, + 70E88BDB3FDACE8F2B23F3247435107D /* ConstraintLayoutGuide.swift */, + 5EE456287EB50E4B04F1A29EC19043B7 /* ConstraintLayoutGuide+Extensions.swift */, + 1245F46A35053D954B8985EFAFD068D7 /* ConstraintLayoutGuideDSL.swift */, + 544353E196F6C41D2674EF54DDCED631 /* ConstraintLayoutSupport.swift */, + 0F043A0A52D038042BE4B2E250F39C46 /* ConstraintLayoutSupportDSL.swift */, + 9A4757260F219342EC59610827085045 /* ConstraintMaker.swift */, + 4B3CBC4CFD3D5E9ABDC56DDC685EACE4 /* ConstraintMakerEditable.swift */, + FCBDA27A176AE2D1C34BA797339DE8BB /* ConstraintMakerExtendable.swift */, + AB1035777F9D0FAD25F91B78CF571685 /* ConstraintMakerFinalizable.swift */, + 7EEAE2746CE46B4119A1EF4CB96853D4 /* ConstraintMakerPrioritizable.swift */, + FD311A04C42FFDF8D95E30DC09B7EA57 /* ConstraintMakerRelatable.swift */, + CC6BD8F9EB57322C72A42B7031485790 /* ConstraintMakerRelatable+Extensions.swift */, + 551BC954C9673D937C2CA52B935158E1 /* ConstraintMultiplierTarget.swift */, + CFC3023119381C8AA8F1A4F4106F012A /* ConstraintOffsetTarget.swift */, + 3B1648D17E6B6A33B54A7906BC560E10 /* ConstraintPriority.swift */, + 2DBF99060B70E1B6830A780BA2524ADA /* ConstraintPriorityTarget.swift */, + F1F4D4D87CBE3DA68AFC92D6F05636AF /* ConstraintRelatableTarget.swift */, + 464FF18D590547BE7F4826907AFFE76D /* ConstraintRelation.swift */, + CFE40591DCBDB38549AD0FC756F3D616 /* ConstraintView.swift */, + 59BB800622705BC689D002AFE6C24643 /* ConstraintView+Extensions.swift */, + C958AC7215CB092EEC6FA33BD843AC29 /* ConstraintViewDSL.swift */, + 418DA1AEA18C4A4A1E5D84FCB60DA427 /* Debugging.swift */, + 46D532B60E5A862BAED6B9ED6A3A06F7 /* LayoutConstraint.swift */, + D20FD964253D6C1E0040497B2CA5505E /* LayoutConstraintItem.swift */, + F324FE66E2BF9B4B5B507729C64FD069 /* Typealiases.swift */, + 0F3C77A10532266D4C2017D4C5657D22 /* UILayoutSupport+Extensions.swift */, + D5089C05AA8DF4AEE19DA89A217C7CD8 /* Support Files */, ); - name = "Pods-SmartCodable_Example"; - path = "Target Support Files/Pods-SmartCodable_Example"; + name = SnapKit; + path = SnapKit; sourceTree = ""; }; - CF1408CF629C7361332E53B88F7BD30C = { + E407636689F088725517C5D0D8F9824C /* JSONDecoder */ = { isa = PBXGroup; children = ( - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - 1FBE93D339BAC3963058FE11DE9AB77B /* Development Pods */, - B94D7768568A9992200DB461E8CF687F /* Frameworks */, - C4E32CAEB27EC1CA6AA0E99359E38370 /* Pods */, - 8EB303108F4B4E4275CE95FED804AF48 /* Products */, - 16C17349BA1B06E17DADE08F8DFF5502 /* Targets Support Files */, + C00BDBDD99AEB786E744B3445CBC66DD /* Decoder */, + F91712C0B25380C7ED41D9570A47A5A6 /* Patcher */, ); + name = JSONDecoder; + path = SmartCodable/Classes/JSONDecoder; sourceTree = ""; }; - D0F9D9049AB85A6F36C4FFE5555DCD5F /* CleanJSON */ = { + E4D8ED149F3D4662ACD8B9384FC69FBC /* Container */ = { isa = PBXGroup; children = ( - 929712FD14C65CBAF44B3BA838DCFB36 /* _CleanJSONDecoder.swift */, - DC98C8117F3B1431C854A9C6B4F8FE02 /* _CleanJSONDecoder+Decode.swift */, - 94F201352441D0808E12B12C1B02950B /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */, - E7F41D39907C3886957DEB2668992022 /* _CleanJSONDecoder+Unbox.swift */, - 0269A1B2522AF958CF8C0F8F70F0621A /* CaseDefaultable.swift */, - 3ABF6303B4915731785B890B96086080 /* CleanDecoder.swift */, - A81B9DCB1C5F346CFD0DDFE4DBB79691 /* CleanJSONDecoder.swift */, - C357740AEE6772021A24F0E4114A600F /* CleanJSONDecodingStorage.swift */, - 4F5FEADCF099B87D561589E2F744AE16 /* CleanJSONKey.swift */, - D410A3C5F8C66EF9FB1F780E3A614657 /* CleanJSONKeyedDecodingContainer.swift */, - 837D4D1D0F21909CC79D931A54D8C932 /* CleanJSONUnkeyedDecodingContainer.swift */, - 815ECC31D5B46D1C6B8D579980A78AC2 /* CodingKeysConverter.swift */, - D292372E6836D90D57FB9F067F486A11 /* DecodingError+CleanJSON.swift */, - 63165FEB321973E0AD39AFA539EBD85F /* DecodingStrategy.swift */, - 85D8102D03B9C841FD3EC7FC419350D7 /* Defaultable.swift */, - 54CFEEBCF51169AF0B1F315D69C8D33F /* JSONAdapter.swift */, - B68373D3DB223AC11F1B7D84FCDBFC8A /* ToJSON.swift */, - 8B99E941704955E913B59A4D2AEEFA80 /* Support Files */, + A81A3A6F1AC972F8A54272A3F0CD7B26 /* JSONKeyedEncodingContainer.swift */, + 8EF8CFAD648CDD728E621EF9F95D03A0 /* JSONSingleValueEncodingContainer.swift */, + 7807886D9111CBFB4ACB76EBC0B3D39F /* JSONUnkeyedEncodingContainer.swift */, ); - name = CleanJSON; - path = CleanJSON; + name = Container; + path = Container; sourceTree = ""; }; - D59CBB92C7D1D94ECA4A9CFEDC13B442 /* Decoder */ = { + E58AF6FD854CFA3E8C95C4B2408DBD50 /* Pod */ = { isa = PBXGroup; children = ( - 4E81302FD66DAE30D32CDED9F8F953D9 /* _SmartJSONDecoder.swift */, - 8C12AEF40FFC99AB7F38B2B64D66EE7E /* _SmartJSONDecoder+Unbox.swift */, - 3D07A0B1D2259F30D4DB6EA5C979D6D8 /* InitialModelCache.swift */, - 59FD30BFD517239EAEF40A0E82542733 /* ModelKeyMapper.swift */, - 54221FFC83764C52FD659D644D6F1ED8 /* SmartJSONDecoder.swift */, - 1187CAE253A8264680CBBC4D3BF3AE54 /* SmartJSONDecodingStorage.swift */, - 3A7336366091CEA7AA3B99B1550BB520 /* SmartKeyDecodingStrategy.swift */, + FB8DBD5CFA5CEBDCE3E21C0F74DF249C /* LICENSE */, + B7FDF252ED60310F04697FD38BA56AE6 /* README.md */, + 89D27D01563CE1DAAD49F56EC8284738 /* SmartCodable.podspec */, ); - name = Decoder; - path = Decoder; + name = Pod; sourceTree = ""; }; - E37982B78A2E61A0C063B3D369D9287F /* SmartCodable */ = { + F02A47C6E8279678BBAFA51319D05818 /* BTPrint */ = { isa = PBXGroup; children = ( - 8224719BF93802AC51382B196A6B30C5 /* IgnoredKey.swift */, - 46A766AE91E8CF4C4930E74AD1BF9210 /* SmartAny.swift */, - 56F0CCA54FAF427CF38B01CBAAE7E03D /* SmartCaseDefaultable.swift */, - 2B5009BA615F605E4770A0F999C8EAC7 /* SmartCodable.swift */, - 70B952A2FD0BD10A80C59B2F4BE7F89C /* SmartDecodable.swift */, - 95129AD448C6FA92BE25187E54E7D541 /* SmartEncodable.swift */, + 68F996F21CE4381BFEAC8BDD8BC5E788 /* BTPrint.swift */, + 7F9222551C78E09BFE29291610498A56 /* PrintFormat.swift */, + 1EC73E5802EDCA8941212E2C0320FD68 /* Support Files */, ); - name = SmartCodable; - path = SmartCodable/Classes/SmartCodable; + name = BTPrint; + path = BTPrint; sourceTree = ""; }; - E888A1EE2825DA495FC34D225BF77FDB /* Support Files */ = { + F6CB312492D55F536B99CE8051B6012A /* CleanJSON */ = { isa = PBXGroup; children = ( - 4F8809F9A3B10DEA6DCA3CC98E08D622 /* BTPrint.modulemap */, - 4CA7F1846B98306446ECE67F2856D9BB /* BTPrint-dummy.m */, - 6E36C3087AA75ECBCF695349CB5A749B /* BTPrint-Info.plist */, - 8E7E6CC166BDB2FBE80EA3AEC615AA57 /* BTPrint-prefix.pch */, - 15CC97091BEEC9AAC898E58EC68EBF05 /* BTPrint-umbrella.h */, - C538963150450AD6377ACBE6ECAB0F31 /* BTPrint.debug.xcconfig */, - 7C5723CCC9FB17ECAE18AE1F0A10DC5C /* BTPrint.release.xcconfig */, + 07ADF3C4B3DE46FA90A67725C575E757 /* _CleanJSONDecoder.swift */, + A247AF8B486EBFFB5B5CED8A27FD6D94 /* _CleanJSONDecoder+Decode.swift */, + 5DAD6DAD58F97DC6978669ECC1DCB217 /* _CleanJSONDecoder+SingleValueDecodingContainer.swift */, + C7BBDFD017622786401A39F6BD9686C8 /* _CleanJSONDecoder+Unbox.swift */, + EBDE8674ED579EE94A0773028BD44AF1 /* CaseDefaultable.swift */, + B8F06552F963B43848600AFDC8043A19 /* CleanDecoder.swift */, + DB06E31B883A63C5DE4A5A6308F36C8F /* CleanJSONDecoder.swift */, + BF34C278263A81DD03B77202C061698C /* CleanJSONDecodingStorage.swift */, + 555C1F46B8C3D9749B4FADF32ED4458D /* CleanJSONKey.swift */, + 6DFBE39A8F2F3352B5AB28C6FFC990E7 /* CleanJSONKeyedDecodingContainer.swift */, + 39B2DBA2FFE481C74723D3D77C1C4151 /* CleanJSONUnkeyedDecodingContainer.swift */, + 6CDB55010FADC798A0E3768269292E5E /* CodingKeysConverter.swift */, + B9E5E84322D1072C445D51381EACDD7D /* DecodingError+CleanJSON.swift */, + 2D804957148656B5405037FC4821F4DB /* DecodingStrategy.swift */, + 541A55046863031E15A9FA69EA99FE8E /* Defaultable.swift */, + 1A2453FB81C81C62905E16C3FD41C15D /* JSONAdapter.swift */, + 9121AADFDAA9E940775A36390D6DDBC7 /* ToJSON.swift */, + 98C45354D057DFD460070868850871E7 /* Support Files */, ); - name = "Support Files"; - path = "../Target Support Files/BTPrint"; + name = CleanJSON; + path = CleanJSON; sourceTree = ""; }; - EA3357C6F6D23120B432667D8921CA9F /* SmartCodable */ = { + F91712C0B25380C7ED41D9570A47A5A6 /* Patcher */ = { isa = PBXGroup; children = ( - 586A854BCE5668A684B2847ACD79F494 /* JSONDecoder */, - 94416DF3087C68B20F2B70D8B0FF8380 /* Log */, - BCFDD7DCD36ED406EDDD79DCCFC876B4 /* Pod */, - E37982B78A2E61A0C063B3D369D9287F /* SmartCodable */, - 64574C69C8EE6DD4B5AC15F28A5E6BB4 /* Support Files */, - FACA7BAC8504A8F42B6839F078D22860 /* Transformer */, + EA87DC4C55FBD71FD524E23BC5B638D4 /* Patcher.swift */, + FEB73C0BFC8A0BCE1F336584FF0D0236 /* Patcher+Provider.swift */, + A698925A05268E73A17E232B6FB6FAC6 /* Patcher+Transformer.swift */, ); - name = SmartCodable; - path = ../..; + name = Patcher; + path = Patcher; sourceTree = ""; }; - F56461ADED17BDA1F85D7260A92CD90D /* SnapKit */ = { + FB2668559AE577E6E8078C0C291AD417 /* iOS */ = { isa = PBXGroup; children = ( - F3BD359F43CC6E82E7AC095DEFB667F6 /* Constraint.swift */, - BC9FD46ECA8E8E5EF9E6B7EB1AF5495D /* ConstraintAttributes.swift */, - 74D8B544917AB1825600223F1847F8ED /* ConstraintConfig.swift */, - F9BFA8B0590A57660EC2A37A517822E3 /* ConstraintConstantTarget.swift */, - 9B544865E9FB982351862D454EB97A62 /* ConstraintDescription.swift */, - 4CBB539F9E04B803B7BA7228A07C5BEC /* ConstraintDirectionalInsets.swift */, - 0E57B503B4EBCFD7AA0E51360A97AE18 /* ConstraintDirectionalInsetTarget.swift */, - 14972CEEF09B3920E3ED07D20713219B /* ConstraintDSL.swift */, - 16AD943F9AA80E1E0F94A0D7B760B5BA /* ConstraintInsets.swift */, - 929C4FE20402ECA721BAE7E722B6E523 /* ConstraintInsetTarget.swift */, - EC4A1138AA274CD1E4839F0548F25126 /* ConstraintItem.swift */, - 28F8F94803B65B561FBB046FCFCE4EA7 /* ConstraintLayoutGuide.swift */, - 39C04B27E6710C0E07FB4EEEA8231088 /* ConstraintLayoutGuide+Extensions.swift */, - 70EB956D11844218C49F91382D5686BB /* ConstraintLayoutGuideDSL.swift */, - B780DB2E145B03662828DEC1C5D1132F /* ConstraintLayoutSupport.swift */, - 6D22BA786978818F4FE3FDB91C56F4A1 /* ConstraintLayoutSupportDSL.swift */, - B35C9C2671C107A19B97A31FB4CC5BEA /* ConstraintMaker.swift */, - 8BC254FD8EC10D39D0B946E545B0AC6D /* ConstraintMakerEditable.swift */, - 186F0AB785FEFD705F9810BF829E3B9F /* ConstraintMakerExtendable.swift */, - 4A63818CFAB3CDEB4D9CE9D9BABC4541 /* ConstraintMakerFinalizable.swift */, - D28D7943409E3C2F68D7F7BFD3C05A1C /* ConstraintMakerPrioritizable.swift */, - FE9E48CF5B436F03A644A3F2079E06A5 /* ConstraintMakerRelatable.swift */, - 1D0B07DBB6CE6B51956B3F9FCE907678 /* ConstraintMakerRelatable+Extensions.swift */, - EF0FA79118EA6C707BFE21F070594989 /* ConstraintMultiplierTarget.swift */, - AE3301D1CE71A4E0C1D2991CAB2A9207 /* ConstraintOffsetTarget.swift */, - 60AD687D99290D39682062FBAB4B9530 /* ConstraintPriority.swift */, - 327DC9387C1368E032434452F72153B7 /* ConstraintPriorityTarget.swift */, - 4841EAB23923FDF7466BD02E50A85A28 /* ConstraintRelatableTarget.swift */, - B1ABE47C1F1223A420137396A81E391B /* ConstraintRelation.swift */, - 9A0CDA24DDDB701970130A91AE5FA140 /* ConstraintView.swift */, - FC8E9C700F20DBFB07454F509557FF17 /* ConstraintView+Extensions.swift */, - B27DA73869030B61A7DD375B3D22632A /* ConstraintViewDSL.swift */, - ADDAA04F64E571FD4FDEB5F3133A447A /* Debugging.swift */, - B81E6BEF09C7E97AF72776F1CA7F474A /* LayoutConstraint.swift */, - D18D6541EFE81AFDF8F5EB531B779D4D /* LayoutConstraintItem.swift */, - 017E9F0474BFE7DA39821ABE5ED3C7D3 /* Typealiases.swift */, - 1C620067F708F6A1819086FB1A562860 /* UILayoutSupport+Extensions.swift */, - 15FD889B319764E25F2C07EBB5840C58 /* Support Files */, + 57221B54D014471C3D3E1925EFC917C8 /* Foundation.framework */, + 3280BB5E7B57C31D41117A74F76E9DF3 /* QuartzCore.framework */, + 1DA24A38BA9EE106B59E3D4C8DD1CE0E /* UIKit.framework */, + E658F388F01C72599CA75537950B6095 /* XCTest.framework */, ); - name = SnapKit; - path = SnapKit; + name = iOS; sourceTree = ""; }; - FACA7BAC8504A8F42B6839F078D22860 /* Transformer */ = { + FDCBEBF5E487956EF93414AE43BD350B /* Pods */ = { isa = PBXGroup; children = ( - 8EBE6B1394A862F1ACAFA1EE0AE8D24E /* ColorTransformer.swift */, - 1FE209EF17490B7AE639036689E60ACF /* DataTransformer.swift */, - 22EEC6388F35D221D7E345FF0D771E29 /* DateTransformer.swift */, - D72D10260E32B90F95F2E7373E81C0C4 /* Transformer.swift */, - B508AD354731149BE19FE9B19292E30C /* URLTransformer.swift */, + 47E83401A7A3D80C30C5C1DF7F4429F2 /* BTBubble */, + F02A47C6E8279678BBAFA51319D05818 /* BTPrint */, + F6CB312492D55F536B99CE8051B6012A /* CleanJSON */, + 049FFF5761BF7F049DF9C98EFCC022EF /* FBSnapshotTestCase */, + 4261FFE260332A8857E6A48C5BD8E0CB /* HandyJSON */, + E0646F01706B42305D43ED181AB83900 /* SnapKit */, ); - name = Transformer; - path = SmartCodable/Classes/Transformer; + name = Pods; sourceTree = ""; }; FE9C729707A5477C1EF6D1BFC9BB59FA /* Pods-SmartCodable_Tests */ = { @@ -2032,33 +1164,6 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 0A7B0C2CCCEED8481FB7DB6EBC707B77 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 580FE14211553843A3CDF2B13DC97E6C /* SQLite-Bridging.h in Headers */, - 84A72ABBDFDDC959E298C0107A6C4BE7 /* WCDB-Bridging.h in Headers */, - C6E090B7A89D40489E53D4B5B48EE191 /* WCDB.swift-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1EC8C72BAE3E2192374780812E859570 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - DD31E7350864163520D060B45194A91D /* SQLiteRepairKit.h in Headers */, - F22287A421E09D8A9D13605580F74C49 /* SQLiteRepairKit-umbrella.h in Headers */, - 36E9CA298A5928DF3351A92DA4A59C32 /* sqliterk.h in Headers */, - F00096B4E2DD0B1EEFAAB8E630A8EF0A /* sqliterk_btree.h in Headers */, - BADEFEFE78C547F20032D251D25C3031 /* sqliterk_column.h in Headers */, - D97C3A1A45117372E374C9AEE0EF9C0E /* sqliterk_crypto.h in Headers */, - 3A303FCED61BCB29B3FD26735BB9889F /* sqliterk_os.h in Headers */, - 21B71CBFE18C8A24D9198B694A6BE31E /* sqliterk_pager.h in Headers */, - A51491E2BECD0FDFC6B28CCDE8CAA2D6 /* sqliterk_util.h in Headers */, - B4AB5333566AF99D8865EAE0427DE941 /* sqliterk_values.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5FA4790A32ECD84F2CEA55509107BD0A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2083,14 +1188,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6FC7C3C5923226BE4E0D7E33C31B3901 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 3A931F2D706945121204F41FFB56DABD /* SmartCodable-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 6FC876053E92670778D608CA0478F728 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2116,58 +1213,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 96E537AE0D0C50394E09F8F3BA3A3358 /* Headers */ = { + 964D512BF22224583805C80F50913513 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - BA3E240FF7C7BF3E385ED6DC89345EFB /* Pods-SmartCodable_Example-umbrella.h in Headers */, + 5FF5ED34372D682A95644DCC006F2E0E /* SmartCodable-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - C807DA476C44FCE7C7E1E5B071A360A2 /* Headers */ = { + 96D3F1763A97C7BB5A2F75D1B40B4C6B /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 116592853664BF5C14932F7FACFBD65F /* btree.h in Headers */, - 2B8005A25AB53F75BF876C529F2E8A4F /* btreeInt.h in Headers */, - F13E9D5DE4C7A4ADD067181C5A737608 /* crypto.h in Headers */, - 45ED255F3838C9661EAFA906F8BA79DB /* fts3.h in Headers */, - 99C79FC97E865A2578C62C18939A3E83 /* fts3_hash.h in Headers */, - 500C3D73A19D8FD96D70B00D4B23CB60 /* fts3_tokenizer.h in Headers */, - FC135EE0D06EC79DA984EEE013A50210 /* fts3Int.h in Headers */, - 7278EB29E9242FF7FA58F3B0B1184113 /* fts5.h in Headers */, - 443F8883D7EB29311780684738AE71A0 /* hash.h in Headers */, - 955A00E1FE013891C9A33C1E78AA5A8B /* hwtime.h in Headers */, - E6B73B0F8C83B587483D0C1E9BA6E813 /* keywordhash.h in Headers */, - 847D3774A5E68799F8F05900F07389DE /* msvc.h in Headers */, - 1ED0F18831A8F84E9F989991DF54AD5D /* mutex.h in Headers */, - 67091BB18EA8BF6913739688AB7FDD03 /* mutex_wcdb.h in Headers */, - A213CE0BBBBE1F4E97A2CDFF6DF512BB /* opcodes.h in Headers */, - EF39224E16AAA9ED26CDA0C9C77EA658 /* os.h in Headers */, - 8B9C123C6DFE8CAA1CF7382D30030372 /* os_common.h in Headers */, - D9AB41F2BB09E85EB79CD789ACB3DBBF /* os_setup.h in Headers */, - 75B9D189221C4D0E9E306F3006999943 /* os_wcdb.h in Headers */, - 1DF22A9F17E1CFAF5E59338E22FC4ECD /* pager.h in Headers */, - AEDB5D6AD5FE1F510B11F2BDD3DA2335 /* parse.h in Headers */, - 6E4CE8F3BEAA64D17F48765F8D1B7419 /* pcache.h in Headers */, - 6884451BA4699A47772D4520DFB56629 /* pragma.h in Headers */, - 45B320FB7573471F838C781BC975C2AA /* queue.h in Headers */, - 3AB098E905CC590F7D3FD840511EA3E3 /* rtree.h in Headers */, - 689851F4B65EB0613B61C6CE8F0A8CFB /* sqlcipher.h in Headers */, - E222ED79C3BB38A273543B2D2B4D1013 /* sqlite3.h in Headers */, - 269A21F134292C4A451050823CB92255 /* sqlite3ext.h in Headers */, - 42C3DF2D76E9E3E9AA70B53407AF0072 /* sqlite3rbu.h in Headers */, - B19DC048E870298A604D3A4191F60CFF /* sqlite3rtree.h in Headers */, - 06F077368CE7C4C411228D0BFBC3522E /* sqlite3userauth.h in Headers */, - 3E78F4F6E99E13A7CB10FAF2A5292797 /* sqliteicu.h in Headers */, - 5BAF79C63655A4F5CE51D5766A12BA4B /* sqliteInt.h in Headers */, - F9E696447A065C063BDBD133CC0FA0EF /* sqliteLimit.h in Headers */, - 56DA284ABCBA338B207BC5CDDEA1D687 /* vdbe.h in Headers */, - B26F8523031ADC544BF2707EA4F81778 /* vdbeInt.h in Headers */, - FF2FB2EDD6A5B73BA83F8ECFC6B565DF /* vxworks.h in Headers */, - 38D8B03AFC5B21317B7F8C0F21321E9D /* wal.h in Headers */, - FEE368E42177BB460ACE0A3122223FB2 /* WCDBOptimizedSQLCipher-umbrella.h in Headers */, - D4E5BC7906B48C020613918044DC8CB0 /* whereInt.h in Headers */, + AA75627FBC8A28CB9F9E26CDE0062EFE /* Pods-SmartCodable_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2201,8 +1259,8 @@ buildRules = ( ); dependencies = ( - A8D2A03FFB1DB27EA483E2D86AA9C93F /* PBXTargetDependency */, - E5AB5F2253E00CE0F85F97D8A2595023 /* PBXTargetDependency */, + 8690E19EE3153A0BF1810EDD5FD7BDDE /* PBXTargetDependency */, + C329BE7457273DA9C3CF4C12382AD999 /* PBXTargetDependency */, ); name = "Pods-SmartCodable_Tests"; productName = Pods_SmartCodable_Tests; @@ -2263,43 +1321,6 @@ productReference = D9B8AA14A5BB1D0CE3A003CB6A566265 /* CleanJSON */; productType = "com.apple.product-type.framework"; }; - 46B68FB361B0E581CECCA815555333A6 /* SQLiteRepairKit */ = { - isa = PBXNativeTarget; - buildConfigurationList = BA746E6B99FD9FFB73AC7236870D7DF5 /* Build configuration list for PBXNativeTarget "SQLiteRepairKit" */; - buildPhases = ( - 1EC8C72BAE3E2192374780812E859570 /* Headers */, - 5FFCE13DD541F04DFA678552E430951B /* Sources */, - F715C66328463B5C993B81AB0FE02F75 /* Frameworks */, - E415302AB5822223D9DCFB970DF7235B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - FEF83CF6F2327A700A68A1AA13C33AF4 /* PBXTargetDependency */, - ); - name = SQLiteRepairKit; - productName = sqliterk; - productReference = 5DCCF5B5F792D4EC76585F50AC7D8D7B /* SQLiteRepairKit */; - productType = "com.apple.product-type.framework"; - }; - 7AC2C6E1735146F1E0A04614976C5D18 /* WCDBOptimizedSQLCipher */ = { - isa = PBXNativeTarget; - buildConfigurationList = C104640870A0FD010B2F89DD2D2CEF43 /* Build configuration list for PBXNativeTarget "WCDBOptimizedSQLCipher" */; - buildPhases = ( - C807DA476C44FCE7C7E1E5B071A360A2 /* Headers */, - 0F1F4F3700E0B3744A0C318969ED3A67 /* Sources */, - 432508833C2857AC2B59098AE7E52E38 /* Frameworks */, - A247251D65E571A2E3143146B6CAE19C /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WCDBOptimizedSQLCipher; - productName = sqlcipher; - productReference = B3CF92365D6AE0F35C3602CF6C0872AE /* WCDBOptimizedSQLCipher */; - productType = "com.apple.product-type.framework"; - }; 86A81D2B2BFEFD93197A1D6C3C7EF60A /* BTPrint */ = { isa = PBXNativeTarget; buildConfigurationList = D7119D7A8BDBCCBABD7051B90C53F405 /* Build configuration list for PBXNativeTarget "BTPrint" */; @@ -2356,25 +1377,22 @@ }; B8474377209826CA7C2ADD548D40C1EA /* Pods-SmartCodable_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = 9E702437A4BF298D70F6D6B0ECE32307 /* Build configuration list for PBXNativeTarget "Pods-SmartCodable_Example" */; + buildConfigurationList = EEFE656F00195B2CDB67EF4B5BA1AB91 /* Build configuration list for PBXNativeTarget "Pods-SmartCodable_Example" */; buildPhases = ( - 96E537AE0D0C50394E09F8F3BA3A3358 /* Headers */, - B9313AF27EF883B896196B5D9644DDD3 /* Sources */, - 24F210FE791EABA40F88F126F26F2C70 /* Frameworks */, - 6085711B2C2CD51078A5D400556309A3 /* Resources */, + 96D3F1763A97C7BB5A2F75D1B40B4C6B /* Headers */, + 8674B2205AA757724FE8DE2887B93BC0 /* Sources */, + 2E43F8ADC875BC80E2A873F01E86FB3B /* Frameworks */, + B2F14DBF469CA27BCA557E279D69A1D6 /* Resources */, ); buildRules = ( ); dependencies = ( - 762DC7FF6810645A35FE9793E071EC06 /* PBXTargetDependency */, - DAF1895C1F6D00EC3C30D43962E16E1B /* PBXTargetDependency */, - 8E666582D4150CAD6B89A8EEF923720C /* PBXTargetDependency */, - FF79D4D1BE3A227B40A6B8F23D2F0D69 /* PBXTargetDependency */, - 2C51F5A5768BAD7567CA9CC07F8821FF /* PBXTargetDependency */, - 131310F3AE696F52A24210717B552ED5 /* PBXTargetDependency */, - 1B58CE0B5CB6C3667A7E6E224A2F2410 /* PBXTargetDependency */, - DB6ACB409436BD85BDE53205E591D858 /* PBXTargetDependency */, - BF42F7D66A5045394A6A3D74BCFE3C17 /* PBXTargetDependency */, + EED534DC847B4CA3704C063404A47CD6 /* PBXTargetDependency */, + EB2CFCDE9382A1AA030D94162B1BFA87 /* PBXTargetDependency */, + CAC1FAAE9431692C8EA0CF8647B651E4 /* PBXTargetDependency */, + EF426E622C3413F6D2902CD32672AE12 /* PBXTargetDependency */, + 9DF47B28B0EE0EA68BF1CFD041F748E1 /* PBXTargetDependency */, + 152CD6916FBD6BCF970958AA1A9EF19F /* PBXTargetDependency */, ); name = "Pods-SmartCodable_Example"; productName = Pods_SmartCodable_Example; @@ -2383,12 +1401,12 @@ }; BD33823B9D08265B6F1D35EC259EE307 /* SmartCodable */ = { isa = PBXNativeTarget; - buildConfigurationList = 4DCF6E1F842BD49DDCD5581FD4574A3F /* Build configuration list for PBXNativeTarget "SmartCodable" */; + buildConfigurationList = 2AF085A0B480398B9D3367C15D32863B /* Build configuration list for PBXNativeTarget "SmartCodable" */; buildPhases = ( - 6FC7C3C5923226BE4E0D7E33C31B3901 /* Headers */, - FEFA6D8883620C16AFBDA907752C98FF /* Sources */, - F751BAAE56D8FE399B415F5705050E96 /* Frameworks */, - A8AF4D478F8087D575B1FFB17900CC1A /* Resources */, + 964D512BF22224583805C80F50913513 /* Headers */, + 6CAE819CFB60B6DCB4FF6BBC86EBEF7F /* Sources */, + 81AB633758722BCEBBC343F8868CA1E1 /* Frameworks */, + F62AF394CF7C09DE52B37FAB769506CA /* Resources */, ); buildRules = ( ); @@ -2399,26 +1417,6 @@ productReference = 3E623AAE662B463FDDE8B268BDEA3E7B /* SmartCodable */; productType = "com.apple.product-type.framework"; }; - CA298FF53B6D582AE40929DFE1454BBD /* WCDB.swift */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9A610C44286ED4C638C6B1CCF09426DB /* Build configuration list for PBXNativeTarget "WCDB.swift" */; - buildPhases = ( - 0A7B0C2CCCEED8481FB7DB6EBC707B77 /* Headers */, - D379BDF18069C4B1B81852B3BCD37978 /* Sources */, - F929D5DFC96C72A9863CDE240F75BDC6 /* Frameworks */, - 82F2833B0194C144E888C0FD4A7D8596 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - F3CD96A1D8AC1056F364198F1894D38E /* PBXTargetDependency */, - 771D5E93CE85D1419EFE4D94C9C53DCA /* PBXTargetDependency */, - ); - name = WCDB.swift; - productName = WCDBSwift; - productReference = 3A669A12B69A63E0BEF5B0382A3A729B /* WCDB.swift */; - productType = "com.apple.product-type.framework"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -2437,7 +1435,7 @@ en, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 8EB303108F4B4E4275CE95FED804AF48 /* Products */; + productRefGroup = 31D698C122DAC16CE786204DDC7267E6 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( @@ -2450,9 +1448,6 @@ 017FF54E0A886D69E40DEE3BD4F2F1DF /* Pods-SmartCodable_Tests */, BD33823B9D08265B6F1D35EC259EE307 /* SmartCodable */, 19622742EBA51E823D6DAE3F8CDBFAD4 /* SnapKit */, - 46B68FB361B0E581CECCA815555333A6 /* SQLiteRepairKit */, - CA298FF53B6D582AE40929DFE1454BBD /* WCDB.swift */, - 7AC2C6E1735146F1E0A04614976C5D18 /* WCDBOptimizedSQLCipher */, ); }; /* End PBXProject section */ @@ -2486,14 +1481,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6085711B2C2CD51078A5D400556309A3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7BBEEC7A97C07C1990B46249A15F7AFF /* Resources */ = { + 7BBEEC7A97C07C1990B46249A15F7AFF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2507,21 +1495,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 82F2833B0194C144E888C0FD4A7D8596 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A247251D65E571A2E3143146B6CAE19C /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A8AF4D478F8087D575B1FFB17900CC1A /* Resources */ = { + B2F14DBF469CA27BCA557E279D69A1D6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2535,7 +1509,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - E415302AB5822223D9DCFB970DF7235B /* Resources */ = { + F62AF394CF7C09DE52B37FAB769506CA /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -2545,114 +1519,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 0F1F4F3700E0B3744A0C318969ED3A67 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8A972E8E412C9318BECC91DCB4ACCAFC /* alter.c in Sources */, - A522DA5E890E3AB1AAF8C7A2A060BF75 /* analyze.c in Sources */, - E0C538B8B9529B46C9F0F08BE0C9A842 /* attach.c in Sources */, - 43AEF76844A559D0319F273F5E688613 /* auth.c in Sources */, - 387D6EF5FCADD267664EFD984CB6265A /* backup.c in Sources */, - 893D219E4A343A71C3E305046ED038F4 /* bitvec.c in Sources */, - 2D3800F3747D531C8793755D6137DF64 /* btmutex.c in Sources */, - 545F820CC9C430626698E3D80323EBB8 /* btree.c in Sources */, - 09770D71BC9E55593D155BB29B2F1FC7 /* build.c in Sources */, - 3EBEC269AF9440CB77BA0140E3C565F5 /* callback.c in Sources */, - A97102F4BCB2B5D01BEF6BDDB7065D81 /* complete.c in Sources */, - 1F1AC390BB78B11FD3F67C5BB9B754C4 /* crypto.c in Sources */, - 91D8E61BF918EFAB8EB9FDC0000956DE /* crypto_cc.c in Sources */, - 2EF27A7A5ECA0D884396986AA39FA134 /* crypto_impl.c in Sources */, - DA79E90A2C23D0DA7C8294C355F9F91C /* crypto_libtomcrypt.c in Sources */, - EDDF5EE6A8B400B82725B26D5F9D1EBC /* ctime.c in Sources */, - 471E3E2EEDB58C3AD3551EB00BB6C2D9 /* date.c in Sources */, - 2646AF70FF516BE8741AF8AB0BB10217 /* dbstat.c in Sources */, - 3C79B19BA1FD57F5C3341E070695C021 /* delete.c in Sources */, - B38BC5C353A00655022949C608D4C10A /* expr.c in Sources */, - 941BDD932AA35EBA6AF6F399183E86D7 /* fault.c in Sources */, - E9EA02CE0BE621BCFDCCF7AA66CE84EC /* fkey.c in Sources */, - D44A699BB95F3FE62CE11178D7E7C1A3 /* fts3.c in Sources */, - 48AD197B8AAB83CF9F6CF02BA286DCA9 /* fts3_aux.c in Sources */, - 2C0C1992B978CADF14B0E06B8499C89E /* fts3_expr.c in Sources */, - F9CF3D400285C0D58996939F543DBBE0 /* fts3_hash.c in Sources */, - F2FE85399D53E6885DC43F57304C6BE6 /* fts3_icu.c in Sources */, - F68E491252989FD39243D0BBC13F67CF /* fts3_porter.c in Sources */, - 14714B4F87060C2206F43EFD8EAE7E23 /* fts3_snippet.c in Sources */, - 277BD70D62A60D10488C2588712D46C7 /* fts3_tokenize_vtab.c in Sources */, - EA62F44B607D3025B0D838D1E6BCDF04 /* fts3_tokenizer.c in Sources */, - 46F8DF51B898A743A704F10A78390817 /* fts3_tokenizer1.c in Sources */, - 268E861FB1940887EE37338C0D99CFBF /* fts3_unicode.c in Sources */, - 2556E6D6E136822FDD7583D50D460C3A /* fts3_unicode2.c in Sources */, - 4DF8F8D5DBF3DC1119AB593C46D045B1 /* fts3_write.c in Sources */, - C2881F0D6A914D4337B1226D3918A70A /* fts5.c in Sources */, - 9040ABAE95AF55340A2FD5A2AE4FB74B /* func.c in Sources */, - CC6E67AE1352C3E8E9F3900EB2B4D478 /* global.c in Sources */, - 21D9A9BF7A6DE6222221999E6400385A /* hash.c in Sources */, - 475FF86E21EF441D2A5EF28F6B254A5F /* icu.c in Sources */, - 97E088B9850A57B244DF543BCEB18FC0 /* insert.c in Sources */, - 792C4E7E6F8093FE273376553AB2A094 /* legacy.c in Sources */, - C0828EC388D79328143D139A1E023556 /* loadext.c in Sources */, - D37F777D759D29E1F7323611B01021D4 /* main.c in Sources */, - 99258493B0865705197B3B2B4DCA39C0 /* malloc.c in Sources */, - FA4062E6B60F8C9FF4DD32907C22B29A /* mem0.c in Sources */, - A3FF41BEF6F5F060F350F8EF4EFB83DF /* mem1.c in Sources */, - CC89AA019D8C987A06DAEA893BD2182E /* mem2.c in Sources */, - 64C86F2C6C930257809E85602113204B /* mem3.c in Sources */, - B93F5B04FEE1DAA927A1E948C601CC88 /* mem5.c in Sources */, - A5B33904555D4808E08DB75C19622D63 /* memjournal.c in Sources */, - 3D8C435D4C19F8220CFC4E18E8E1CA9A /* mutex.c in Sources */, - 2F85152F2FA3BBDB54B8C8AC78C3FB1C /* mutex_noop.c in Sources */, - 68D63EBF0EAD9C0B890613ED127DBC3C /* mutex_unix.c in Sources */, - 3C90C08CA74CC0906DBDD0B4B6AFF100 /* mutex_wcdb.c in Sources */, - 1FBE8E245651194A2F6F63E1AECD92E4 /* notify.c in Sources */, - D79C863A2581DB4910306B5898CC9B9D /* opcodes.c in Sources */, - 91EC3B883BA861D9867A5E59D1939BC0 /* os.c in Sources */, - 03B49B92AB291DFD32642233E5EDB638 /* os_unix.c in Sources */, - 3DDBBEAD85435705CDCF8E55243846CF /* os_wcdb.c in Sources */, - 69C577251E116B8932A0BD60390EF26D /* pager.c in Sources */, - EBE77754FCDDCD5520489E15C7AD435D /* parse.c in Sources */, - 5738F827DE4798236556220F211BC23B /* pcache.c in Sources */, - 990B0A2658464507A4A8028B2E5D2148 /* pcache1.c in Sources */, - 1F097EC7770FD4A1A9A8FD4770037684 /* pragma.c in Sources */, - B1CF055222726FC043CB0448D462258C /* prepare.c in Sources */, - 02485FF1AE2CAB3D8A57BE62888AF328 /* printf.c in Sources */, - CA997421613DE4D0A8FBC166BB3EBC50 /* queue.c in Sources */, - FDD099F058BC0E5A3A78E4FCEE43A079 /* random.c in Sources */, - 114AD2ADB1B9F746B7A1DF0CB8F93598 /* resolve.c in Sources */, - B8F2663637A011291A4B2931410C401C /* rowset.c in Sources */, - 6768219789457703F7523F533EE56CB5 /* rtree.c in Sources */, - 8087D4C8588A44C31FCA163A64FF58C9 /* select.c in Sources */, - 94F87A9E2D3CE342062B17FFDD03D7E8 /* sqlite3rbu.c in Sources */, - 16B4411868155DC93F0DA1DEC1AAD005 /* status.c in Sources */, - DFB9F2DA1A87F0A1A02C6419A1CCDA9F /* table.c in Sources */, - CDEA17A2C8E2D5F50C6E60D4E1B292E1 /* threads.c in Sources */, - E240EACDE1A9C4313DABBFB7FD401BCE /* tokenize.c in Sources */, - 78BEB406520FC2CBA626639A9F1CE9BD /* treeview.c in Sources */, - 4B15E1711B97D1607B6D3AB5288A7468 /* trigger.c in Sources */, - 5DC73AA815A59F40B06AAAEF2DEAB163 /* update.c in Sources */, - 46BDDFC8D55447DF41D3EB14E31DA934 /* upsert.c in Sources */, - DC22D5FD2A5DE86226E0457F31E9C92F /* userauth.c in Sources */, - E14F3E3E66054690A6434A5C5B1FB68F /* utf.c in Sources */, - 71E9BDC77BBD4811EDCBD86C153DA3BC /* util.c in Sources */, - 67900475325854AFF252C29C05D69122 /* vacuum.c in Sources */, - 14848FEE4EBDB5AC5ACD05E5E9A12280 /* vdbe.c in Sources */, - 5479481080E8B03DAB47E61F67AC3F64 /* vdbeapi.c in Sources */, - C890E34038ED089EB9ACE34DB931C248 /* vdbeaux.c in Sources */, - 49848A2E0517D0DBE730337A2487243D /* vdbeblob.c in Sources */, - 30544F2A4D2D9EC72607B8BDB220FA77 /* vdbemem.c in Sources */, - 7227932727F5F79EB6CF2F04E18DF2FE /* vdbesort.c in Sources */, - B602241CEAB9B07F7156F3235077F8AE /* vdbetrace.c in Sources */, - CA408F2FB0811B1B2DEDCBD4949EA6D6 /* vtab.c in Sources */, - CB4CFD223A869C96E4B943C182793DC9 /* wal.c in Sources */, - 73A29EA24E5EF12889A46883F1AC2818 /* walker.c in Sources */, - AA545F464B606F381AE7B046F93F2068 /* WCDBOptimizedSQLCipher-dummy.m in Sources */, - 6C0F4156A4893EC3E705EEF34D5221AA /* where.c in Sources */, - DF0082F24CE4296BFFB3EF5FADE3ECA2 /* wherecode.c in Sources */, - A1714BD98D3E38B7A52BB8DDBF76F004 /* whereexpr.c in Sources */, - 45F29B90443A2B5B18BCC90E6C49AA15 /* window.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 297006406C018214D4FE588293656EB4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2677,21 +1543,54 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5FFCE13DD541F04DFA678552E430951B /* Sources */ = { + 6CAE819CFB60B6DCB4FF6BBC86EBEF7F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8FC9EBE1D9180F97E4FBAF49FC729D3B /* SQLiteRepairKit-dummy.m in Sources */, - FFAD5D6391D0861FF259F40A208F081C /* sqliterk.c in Sources */, - 138687962513B5FC55762512233493F5 /* sqliterk_api.c in Sources */, - 8EB8C97A9108E89E0975FFF7613FC456 /* sqliterk_btree.c in Sources */, - 9563FB84D29C49072BD3D1387C75FF70 /* sqliterk_column.c in Sources */, - 135DA831CB3A165481A621F982F5AD25 /* sqliterk_crypto.c in Sources */, - A64D032799685FC978C16E7B31CD98B1 /* sqliterk_os.c in Sources */, - A7761020975300C8127387DFDA142850 /* sqliterk_output.cpp in Sources */, - 0A188E966049728E55F6E95C317CC3F5 /* sqliterk_pager.c in Sources */, - ACBC03A430A09775E02C0B3676287DD6 /* sqliterk_util.c in Sources */, - 5DCE38107310E0DD000C18BD3307E496 /* sqliterk_values.c in Sources */, + 716F32806E27B9ECBB08DFFEF04F0687 /* _SpecialTreatmentEncoder.swift in Sources */, + 5AFEE2EFAB9F1F62CCB3D12DA9FCEBAE /* Cachable.swift in Sources */, + 6873423A671225CBD04F0A29E0106C93 /* ColorTransformer.swift in Sources */, + 440B40432B89ED5D2CFD28D7D9500393 /* DataTransformer.swift in Sources */, + 36A5D7A3D1EE0A7C83ED537C7E427ACD /* DateTransformer.swift in Sources */, + 62A19B6E867B83058B1C8A2138EA7C50 /* DecodingCache.swift in Sources */, + 4AB42EE20602D1A2D43EE5BA223F2DD0 /* DecodingError+Extension.swift in Sources */, + D96D4E9317083E36E6CAA29795DAE10E /* EncodingCache.swift in Sources */, + CA37B929250C9E1626AD815019BE9954 /* IgnoredKey.swift in Sources */, + 4F6C6CD873CC992A848865508C54A9A1 /* JSONDecoderImpl.swift in Sources */, + 463073AA2E32EA2F7D5B208B713D828B /* JSONDecoderImpl+KeyedContainer.swift in Sources */, + 31D6011D9AB3D1D13B504508D6CBD0C9 /* JSONDecoderImpl+SingleValueContainer.swift in Sources */, + B48B49F742B16DCAF2A095F3C5B5567D /* JSONDecoderImpl+UnkeyedContainer.swift in Sources */, + 998ED11AB27A87F186FEF60D94B647B9 /* JSONDecoderImpl+unwrap.swift in Sources */, + 7E922AA455A7C6AFF9C4013D66AE30A8 /* JSONEncoderImpl.swift in Sources */, + 0B9BA74A4B04EF2A0957499A7F3ABA6B /* JSONFuture.swift in Sources */, + 78291B1F4027A71FC5DE0A74F491A68C /* JSONKeyedEncodingContainer.swift in Sources */, + D0C420537689BFE4829BDBC476CE326F /* JSONParser.swift in Sources */, + 9B979585D04DE16A51C0D86CBC20F558 /* JSONSingleValueEncodingContainer.swift in Sources */, + AEBDDE282F5DE157BB6A94E40747BA34 /* JSONUnkeyedEncodingContainer.swift in Sources */, + 721D749F257ABA46950E7187EB42D00E /* JSONValue.swift in Sources */, + 4544781E2299B71D125A0404038166D2 /* JSONValue+Extension.swift in Sources */, + 74B0953E6A82E0DDD4A50C6F3A64379B /* KeysMapper.swift in Sources */, + 9092C0B8C31F6B6F13433DD90C34D983 /* LogCache.swift in Sources */, + 673D9C81275141127A8A2774BC595B26 /* LogContainer.swift in Sources */, + 2FCA83552D94DE096535B686ADDFEAD8 /* LogItem.swift in Sources */, + D277ACC49DD7D3C3A660F4E834876790 /* Patcher.swift in Sources */, + 595F6DC1BACD0E22327532D6DD9E1E93 /* Patcher+Provider.swift in Sources */, + 33D8000A56DFDAAE952C15DE08107022 /* Patcher+Transformer.swift in Sources */, + B0CEED2441DE3C86F63B0810A71B3C9B /* SafeDictionary.swift in Sources */, + 793D8DB41D7B4433B884003EA6A306D1 /* SmartAny.swift in Sources */, + A7E56F88A901663F5B7650BE98735031 /* SmartCaseDefaultable.swift in Sources */, + 4F0BC340FCCD023F7F352325D2B22E44 /* SmartCodable.swift in Sources */, + F5B60A9B96EEF8DC4A1772856C6BC0B0 /* SmartCodable-dummy.m in Sources */, + 90125B40656B551C64C1431AED5DB411 /* SmartColor.swift in Sources */, + 317E81440B4BFD37C04396CF32DE59E4 /* SmartDecodable.swift in Sources */, + 3541054BDBB8790FCC7E74D387B59884 /* SmartEncodable.swift in Sources */, + 7A30E1AB144BAFBE0EBFB0A1FF40E6C0 /* SmartJSONDecoder.swift in Sources */, + CEDC7E5C39E615384342D437FD2309AC /* SmartJSONEncoder.swift in Sources */, + 5AE344B70F964CD3F24B43A406D61965 /* SmartKeyDecodingStrategy.swift in Sources */, + 20DBC391BAF1612B228ACF871D5B43D7 /* SmartLog.swift in Sources */, + 2588B6538C39C0F91704795197CA6A3B /* SmartUpdater.swift in Sources */, + B3DBC0B0B13A1A1458147668D370E8E5 /* Transformer.swift in Sources */, + 13AF0E06C5C19F0B6FC9EBB5A56B38D8 /* URLTransformer.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2765,6 +1664,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8674B2205AA757724FE8DE2887B93BC0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8B85D89911D50E1DEAF25D920B6F3C5F /* Pods-SmartCodable_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B186292004011247A56FAC41B9D6C6A2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2808,118 +1715,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - B9313AF27EF883B896196B5D9644DDD3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C586C8D0FD36B229773544DA032D4983 /* Pods-SmartCodable_Example-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D379BDF18069C4B1B81852B3BCD37978 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 59C0CE0F609F6A0C6E5A2A66CCE9B154 /* Atomic.swift in Sources */, - 9EB699629BD092C03AAE47603E6154F9 /* ChainCall.swift in Sources */, - 29224605D129F61D1532BCE2A8614F4E /* CodableType.swift in Sources */, - AB0859F40673A83912F55328A3216F7B /* CodingTableKey.swift in Sources */, - C7BB5FDD6E9E8784CE15BD0611FD1373 /* Column.swift in Sources */, - D0E1AB8968931EFB9C5D2FC9A61C84DD /* ColumnCodable.swift in Sources */, - F07986C1C130CBD0B46BB8AF5453A0A4 /* ColumnConstraintBinding.swift in Sources */, - F177C4754DCBE6015F3F4E2D7DEB89A0 /* ColumnDef.swift in Sources */, - 9BC98C6A1CCC755C0F366463D6D18C14 /* ColumnIndex.swift in Sources */, - B6E9C613E8F15FCA36E4D4AD741191B4 /* ColumnResult.swift in Sources */, - 63B9717578FE35D0E8031F5376631E70 /* ColumnType.swift in Sources */, - 813AFFFBCBD0388DE6FF1673AAE267DB /* ColumnTypeDecoder.swift in Sources */, - 9EF3EE1E656BB216395A6B9F15386E95 /* CommonStatement.swift in Sources */, - CE77259DDCC2A6C2DDE78504F3A694FB /* ConcurrentList.swift in Sources */, - C816257A0FAB5DB746F7BFF1EA4CCF3D /* Config.swift in Sources */, - 4204A64235FD88B9A1F69D071E5E395F /* Conflict.swift in Sources */, - 445236A640179D6E181C4C6E4A0829BE /* Convenience.swift in Sources */, - 1301D909C810F9EC07D5360EC8FB1E8B /* Convertible.swift in Sources */, - 51462C8D3990BE833959AE1F32EF4C41 /* Core.swift in Sources */, - 9D3B496B64C47E6B1812D22D7385F515 /* CoreStatement.swift in Sources */, - 99C3E4EDBE5BCDC161722B105F0FD62F /* Database.swift in Sources */, - C15639E30DB10370C7026D5AE0C5431A /* Declare.swift in Sources */, - DB8CC3D34DDE6C093F96E9356C93763D /* Delete.swift in Sources */, - 4C43602DEBAEEBCD4C2C923BDD23533D /* Describable.swift in Sources */, - 149AA8EC391DDB12B60FAC4501F83FD5 /* Error.swift in Sources */, - F009F0C1E88861F79097F71D7C0E8B21 /* Expression.swift in Sources */, - 3E6B2551A92F752B92AE04D85AD2360F /* File.swift in Sources */, - E802B410A260F85C50E7304C8D90D1BF /* ForeignKey.swift in Sources */, - F707DBE0EE06CC294CE67A076E970012 /* FundamentalValue.swift in Sources */, - B78B71D59862B636ED6F920A0B25C65D /* Handle.swift in Sources */, - 624FA95B57D16D9F791F2B1B0DC7BA84 /* HandlePool.swift in Sources */, - D18A66A416165B614EA8DC0822552D02 /* HandleStatement.swift in Sources */, - C3FA32D5F4FC84BBDFD2D57DAECCC18F /* IndexBinding.swift in Sources */, - D99F0E445BB07122CF9EFC990964BBB9 /* Insert.swift in Sources */, - E4E4787C45F1F154EE662AD931FE9CB0 /* Interface.swift in Sources */, - 0863D5CFCA5BA780AA8C685687F4A034 /* JoinClause.swift in Sources */, - 245DA35A0C392F8A369661C0B1B73653 /* LiteralValue.swift in Sources */, - E0D595792CD84F104894E16543C642F0 /* Lock.swift in Sources */, - ABD796DECC6774A6A3CFA68A265BFBA9 /* Master.swift in Sources */, - F84C542CC3B553CA80228877E02D88E3 /* ModuleArgument.swift in Sources */, - 9F2B1F18D741C08147B423A0AF2E22DC /* MultiSelect.swift in Sources */, - 0E6C5F92B5085DE1351848F5A4BD6EDE /* Operable.swift in Sources */, - 43F4C76847364198EF7A43C247219858 /* Optional.swift in Sources */, - 3E1D9E1EBB1AC16C6639C9CEF65DB151 /* Order.swift in Sources */, - E2FC31BFAF48F12CE9F6AD9867388A1A /* OrderTerm.swift in Sources */, - 1CF436D2F5EA067217400A58CE3256CC /* Pragma.swift in Sources */, - 2029AF0F75B276BC4CF326EAC1D03BAA /* Property.swift in Sources */, - FFF9A5D04B0FFA58870DE24722039326 /* Recyclable.swift in Sources */, - 881F121920DBB09F06C15ABFB7715938 /* RecyclableCore.swift in Sources */, - 0D854DADBA09FA6C54F1511216223D74 /* Redirectable.swift in Sources */, - A8F9C389534594E34C34B08821D67E42 /* RowSelect.swift in Sources */, - 2A25F3EB16B983C2BBE9A0EC0FD9B131 /* RWLock.swift in Sources */, - A41DA75BD15BEBC94523902170EDE87D /* Select.swift in Sources */, - A136BAA6B969F9512DAEDBA3CE3AA6D3 /* Selectable.swift in Sources */, - 1074C42B5CE541D3BB1CED0E33797CBC /* SQLite-Bridging.c in Sources */, - 546CE5582F822B2C395D382A46594897 /* SQLite-Bridging.swift in Sources */, - 96C1D1983D7CDA8566ED049A7EDB49BF /* Statement.swift in Sources */, - 542FCBDA339A22D556E13002BFD717EF /* StatementAlterTable.swift in Sources */, - 9A5C397C4B518E59526372CA6AA0BE65 /* StatementAttach.swift in Sources */, - BA4515FC4EB42075B545BC136AAF21C9 /* StatementCreateIndex.swift in Sources */, - FE2D1B265D2C1BA0588B9D60480058D6 /* StatementCreateTable.swift in Sources */, - 4F529B52D98B333CCF6967D3CAF87AC8 /* StatementCreateVirtualTable.swift in Sources */, - 9B9DA58355282344F0130FDB105ADF79 /* StatementDelete.swift in Sources */, - 55B83E4D45CE7387DE155AFD083F7455 /* StatementDetach.swift in Sources */, - D5A7220BD8FEFE044AA6D6EA87E72F00 /* StatementDropIndex.swift in Sources */, - 96E27528247EE186ABB790A11076678B /* StatementDropTable.swift in Sources */, - F3B5B07B5B37CB65300AAD60D9512B8D /* StatementExplain.swift in Sources */, - 9F9A6624FA895D076FECBBF61491460D /* StatementInsert.swift in Sources */, - 09248AD7A82D172C0DF90D9B9A5A6043 /* StatementPragma.swift in Sources */, - C84D4E3B33D929FD0F86B5D3AE4AADE2 /* StatementReindex.swift in Sources */, - BA8576EA4A18EBBBB8A88175FA55F2B0 /* StatementRelease.swift in Sources */, - 0B5FA55BBADB420979502AA43824502E /* StatementRollback.swift in Sources */, - 754CF78CC23FE72149AF4CB2E1A141B9 /* StatementSavepoint.swift in Sources */, - 9780912475549103BE9BACB1C9CBEEA1 /* StatementSelect.swift in Sources */, - 5ED6076425D3E139315811A196607219 /* StatementTransaction.swift in Sources */, - 8721B511F4B2A7B63C56D9CA080246C0 /* StatementUpdate.swift in Sources */, - DA52AD11094509917C1522D54896C06E /* StatementVacuum.swift in Sources */, - 43B53856DBC504EF1A94D6A14A74E752 /* SteadyClock.swift in Sources */, - DEDE79F24C29684E5F3AB33DDC0EF63F /* Subquery.swift in Sources */, - A23DCC216EC64773E48A293C969964AA /* Table.swift in Sources */, - 01D7C42C2EBCDEE08A99DAA7F9ABDE4A /* TableBinding.swift in Sources */, - A6225D9957CB15D84B5CAFC52C35C4A6 /* TableCodable.swift in Sources */, - 7540E2BE9446FF57C9D2459D20877071 /* TableConstraint.swift in Sources */, - D8DF962A965B6C7B0CBCAC660C86577D /* TableConstraintBinding.swift in Sources */, - 778ED286F78E0C10F3F7D3B1DD2D660E /* TableDecoder.swift in Sources */, - 6FF0CE70CA7D0F8F4B38C403AEB86B59 /* TableEncoder.swift in Sources */, - 599A4EA710D33BB9D940F534BFD58EE6 /* TableInterface.swift in Sources */, - EC5CB815B7B870B9ACD5EE567BF33DAB /* Tagged.swift in Sources */, - 95AA6CBC32B1C295C77C49ED41616A92 /* ThreadLocal.swift in Sources */, - 98238A99285E5720BDC568359D649907 /* TimedQueue.swift in Sources */, - A26B23F738C7F52E17A9F366A4B1A670 /* Tokenize.swift in Sources */, - 171087EAEF2F515323D793C279D98109 /* Tracer.swift in Sources */, - FB405ACA823DA84B63E53210C7327C35 /* Transaction.swift in Sources */, - 6BF9474E1C89F2FC2747B70101798C41 /* Update.swift in Sources */, - 552485DFCAE48E5A29DEFD104DBD7554 /* VirtualTableBinding.swift in Sources */, - AD2508F7D92BF2004FF8ACB8A56A22FF /* WCDB.swift-dummy.m in Sources */, - CA5FB3C081CA09363078DEE45C8B6C90 /* WCDBTokenize.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; EDAA79AE4398595E4B26E0E649205FCB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2946,143 +1741,66 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - FEFA6D8883620C16AFBDA907752C98FF /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D1D8776BB9B31588D346223BCD51C175 /* _SmartJSONDecoder.swift in Sources */, - 3CB868B683BDE4E813CAD9C86B56B033 /* _SmartJSONDecoder+SingleValueDecodingContainer.swift in Sources */, - 839932B8D304C93ABD76ADE280804E70 /* _SmartJSONDecoder+Unbox.swift in Sources */, - FCCCE88FD3EAFE4AFF179F53A9D5672D /* ColorTransformer.swift in Sources */, - 42D3A5AFF2E7B24252CD399BBDC5E654 /* DataTransformer.swift in Sources */, - EB6A3BD0F279EE1512529B050348A725 /* DateTransformer.swift in Sources */, - BA981BA87F28FCB8445B5218A9A14CCA /* DecodingError+Extension.swift in Sources */, - 532888C4FAC628464F216E4FFA56D58C /* DecodingProcessCoordinator.swift in Sources */, - DB3E9FEC1A0797427ECD0DED434EE8AA /* IgnoredKey.swift in Sources */, - 7B0C68363732FB8C3C91E8549F9BD771 /* InitialModelCache.swift in Sources */, - FAA41F3956549234B005B298A106675B /* LogCache.swift in Sources */, - E575B18F4B8BB30FF19D91B1D37E661E /* LogContainer.swift in Sources */, - 2208D53630DF0F336A8D9934D53EA740 /* LogItem.swift in Sources */, - 62F836923F08713C061A1AE9CDC74151 /* ModelKeyMapper.swift in Sources */, - D7834825B2690D47A548E5BADD90B54C /* Patcher.swift in Sources */, - F8A5B347DB74B84AEA04F53922905893 /* Patcher+Provider.swift in Sources */, - A274754305853DD578468EE72BD40C3A /* Patcher+Transformer.swift in Sources */, - AF689A467F60DEC470D6E7A919FE487A /* SmartAny.swift in Sources */, - 04094574EAFF035388C27E465B917745 /* SmartCaseDefaultable.swift in Sources */, - 8A99C5C187ABDD2366D4D3A5A766E615 /* SmartCodable.swift in Sources */, - 96E88CE169F3257187905A8B21B170BB /* SmartCodable-dummy.m in Sources */, - A38BEDD3CD86D876272D2BCC70817194 /* SmartCodingKey.swift in Sources */, - ACC2193BDBA2A9F32319E428E9052433 /* SmartDecodable.swift in Sources */, - 8C6BDCA05022A1CF38F3EC64EE8E30F7 /* SmartEncodable.swift in Sources */, - C3C8AE028E321A1A3A72FA2C94995B01 /* SmartJSONDecoder.swift in Sources */, - 2C701B2907762546B2D793023C3214D7 /* SmartJSONDecodingStorage.swift in Sources */, - C66CE960C72934795BBEB480C5094477 /* SmartJSONKeyedDecodingContainer.swift in Sources */, - B84A210D9E34CB1B5308070B7EF3DEA8 /* SmartJSONKeyedDecodingContainer+decode.swift in Sources */, - A4119C2934A30FEC8130AE0AFC65281B /* SmartJSONKeyedDecodingContainer+decodeIfPresent.swift in Sources */, - 02D671D5D10D160AAB069825595FD4CE /* SmartKeyDecodingStrategy.swift in Sources */, - 7CDFE1663B1A626E3E036AC1891C7206 /* SmartLog.swift in Sources */, - 9ACD167B86B801CE54DD75702AC8F224 /* SmartSONUnkeyedDecodingContainer.swift in Sources */, - 251624DA7D7904D33EB98FC6EAE62CAD /* SmartSONUnkeyedDecodingContainer+decode.swift in Sources */, - CCC3DB9F2FEF5E50AF40EADAC26F72C5 /* Transformer.swift in Sources */, - A0874622A520C7BD11C273BBE3CE953C /* URLTransformer.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 131310F3AE696F52A24210717B552ED5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SmartCodable; - target = BD33823B9D08265B6F1D35EC259EE307 /* SmartCodable */; - targetProxy = 291AF8D092EAF614778FB328CB5A01BB /* PBXContainerItemProxy */; - }; - 1B58CE0B5CB6C3667A7E6E224A2F2410 /* PBXTargetDependency */ = { + 152CD6916FBD6BCF970958AA1A9EF19F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SnapKit; target = 19622742EBA51E823D6DAE3F8CDBFAD4 /* SnapKit */; - targetProxy = 149B2E93D51792ED0408223387C5CFFA /* PBXContainerItemProxy */; + targetProxy = 49E2F178442247BE29DEBD19074B517C /* PBXContainerItemProxy */; }; - 2C51F5A5768BAD7567CA9CC07F8821FF /* PBXTargetDependency */ = { + 8690E19EE3153A0BF1810EDD5FD7BDDE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SQLiteRepairKit; - target = 46B68FB361B0E581CECCA815555333A6 /* SQLiteRepairKit */; - targetProxy = 78B4A1FF9CA093A6212FE27CF20C69A2 /* PBXContainerItemProxy */; + name = FBSnapshotTestCase; + target = 98A98149697C80CEF8D5772791E92E66 /* FBSnapshotTestCase */; + targetProxy = 6315A57DF9B64E5A259DD02D5ED0266F /* PBXContainerItemProxy */; }; - 762DC7FF6810645A35FE9793E071EC06 /* PBXTargetDependency */ = { + 9DF47B28B0EE0EA68BF1CFD041F748E1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = BTBubble; - target = 8ABBD9D5C40976C9B3FC1E227AAC109C /* BTBubble */; - targetProxy = A647F78DF0D8E6CB3697C24A542F283C /* PBXContainerItemProxy */; + name = SmartCodable; + target = BD33823B9D08265B6F1D35EC259EE307 /* SmartCodable */; + targetProxy = 49357A36824C1AEBD1223BCD45855020 /* PBXContainerItemProxy */; }; - 771D5E93CE85D1419EFE4D94C9C53DCA /* PBXTargetDependency */ = { + C329BE7457273DA9C3CF4C12382AD999 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = WCDBOptimizedSQLCipher; - target = 7AC2C6E1735146F1E0A04614976C5D18 /* WCDBOptimizedSQLCipher */; - targetProxy = F24509FBD3F2F499D1BB6497135D42CE /* PBXContainerItemProxy */; + name = "Pods-SmartCodable_Example"; + target = B8474377209826CA7C2ADD548D40C1EA /* Pods-SmartCodable_Example */; + targetProxy = B48F0F8C314B97FBBE684F90D6D7E7B4 /* PBXContainerItemProxy */; }; - 8E666582D4150CAD6B89A8EEF923720C /* PBXTargetDependency */ = { + CAC1FAAE9431692C8EA0CF8647B651E4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = CleanJSON; target = 300904838EEDDC3BB8242817D8F97CB6 /* CleanJSON */; - targetProxy = 56662DD9F2DD6870F9050890F21FF036 /* PBXContainerItemProxy */; + targetProxy = 6E0BBD30A09157B277E47898D23EFCAC /* PBXContainerItemProxy */; }; - A8D2A03FFB1DB27EA483E2D86AA9C93F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = FBSnapshotTestCase; - target = 98A98149697C80CEF8D5772791E92E66 /* FBSnapshotTestCase */; - targetProxy = 0D80BECEC6D0C39E4473C712847963D6 /* PBXContainerItemProxy */; - }; - BF42F7D66A5045394A6A3D74BCFE3C17 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = WCDBOptimizedSQLCipher; - target = 7AC2C6E1735146F1E0A04614976C5D18 /* WCDBOptimizedSQLCipher */; - targetProxy = A89ABCA7FB4E81E34D7A14328380FDBA /* PBXContainerItemProxy */; - }; - DAF1895C1F6D00EC3C30D43962E16E1B /* PBXTargetDependency */ = { + EB2CFCDE9382A1AA030D94162B1BFA87 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = BTPrint; target = 86A81D2B2BFEFD93197A1D6C3C7EF60A /* BTPrint */; - targetProxy = A959223D7063CF06C8F4F6AAB0E60F95 /* PBXContainerItemProxy */; - }; - DB6ACB409436BD85BDE53205E591D858 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = WCDB.swift; - target = CA298FF53B6D582AE40929DFE1454BBD /* WCDB.swift */; - targetProxy = 1E1FAB8076135CEB813BD0C89B3B1BEC /* PBXContainerItemProxy */; - }; - E5AB5F2253E00CE0F85F97D8A2595023 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "Pods-SmartCodable_Example"; - target = B8474377209826CA7C2ADD548D40C1EA /* Pods-SmartCodable_Example */; - targetProxy = 9C2578187BA172FE98132A3A214835D1 /* PBXContainerItemProxy */; + targetProxy = F3D2A2EA822A0F03E6C3B94C16A2BA60 /* PBXContainerItemProxy */; }; - F3CD96A1D8AC1056F364198F1894D38E /* PBXTargetDependency */ = { + EED534DC847B4CA3704C063404A47CD6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = SQLiteRepairKit; - target = 46B68FB361B0E581CECCA815555333A6 /* SQLiteRepairKit */; - targetProxy = 5B82222503485AC3C5895757582545D3 /* PBXContainerItemProxy */; - }; - FEF83CF6F2327A700A68A1AA13C33AF4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = WCDBOptimizedSQLCipher; - target = 7AC2C6E1735146F1E0A04614976C5D18 /* WCDBOptimizedSQLCipher */; - targetProxy = 87CFBEC65473B9ED7865D5DE6D71B9FD /* PBXContainerItemProxy */; + name = BTBubble; + target = 8ABBD9D5C40976C9B3FC1E227AAC109C /* BTBubble */; + targetProxy = D7C8282C3274F6325643139E95457EF5 /* PBXContainerItemProxy */; }; - FF79D4D1BE3A227B40A6B8F23D2F0D69 /* PBXTargetDependency */ = { + EF426E622C3413F6D2902CD32672AE12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = HandyJSON; target = 10D88C24864319FF583AD6D156896F32 /* HandyJSON */; - targetProxy = CD56A044224A6CD0300BAEEF44B16369 /* PBXContainerItemProxy */; + targetProxy = 94237F2B4B215E198D13C2E1DB5AF7CA /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 1453034DB53581D4BB2135BBB0094ECD /* Release */ = { + 0ADE2129E118C010761FBB9D2337D627 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9DD5BACBA6C6D7D9023F4EEAEF6AA63F /* HandyJSON.release.xcconfig */; + baseConfigurationReference = ACA8ECF0DA97BC31739DBB05EDA01B23 /* SmartCodable.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -3091,31 +1809,29 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/HandyJSON/HandyJSON-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/HandyJSON/HandyJSON-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/SmartCodable/SmartCodable-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SmartCodable/SmartCodable-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/HandyJSON/HandyJSON.modulemap"; - PRODUCT_MODULE_NAME = HandyJSON; - PRODUCT_NAME = HandyJSON; + MODULEMAP_FILE = "Target Support Files/SmartCodable/SmartCodable.modulemap"; + PRODUCT_MODULE_NAME = SmartCodable; + PRODUCT_NAME = SmartCodable; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 14DC611A6D2A41704EA1E9C1A32E273B /* Release */ = { + 1453034DB53581D4BB2135BBB0094ECD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6170F13C22D7194151A678E232C31D12 /* Pods-SmartCodable_Example.release.xcconfig */; + baseConfigurationReference = 6CF935F6F0BF80B0C79325C2A66921C8 /* HandyJSON.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -3124,19 +1840,17 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/HandyJSON/HandyJSON-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HandyJSON/HandyJSON-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/HandyJSON/HandyJSON.modulemap"; + PRODUCT_MODULE_NAME = HandyJSON; + PRODUCT_NAME = HandyJSON; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -3146,7 +1860,7 @@ }; 1D30A40E8BEDDA4A0CD0C3E03D28EFC6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DC8CB60731C501F663A8ABBBFBAC4FCC /* FBSnapshotTestCase.debug.xcconfig */; + baseConfigurationReference = 2565E609AC51A4E4FCA81F2594C690F6 /* FBSnapshotTestCase.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3177,7 +1891,7 @@ }; 1DE12B227985D46524C8BBDDCD2F10BD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 55309A18A8E224B31E20FF7DA75F1AE7 /* FBSnapshotTestCase.release.xcconfig */; + baseConfigurationReference = 3E6F38F38A655D1D2F8385D4A13D03BD /* FBSnapshotTestCase.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3207,72 +1921,9 @@ }; name = Release; }; - 28FC5F8B4C8EA087472687C5057C6D66 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 57112FF9C13E952D32767DE7E52A6998 /* WCDBOptimizedSQLCipher.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap"; - PRODUCT_MODULE_NAME = sqlcipher; - PRODUCT_NAME = sqlcipher; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 30B5C0533BF877BCCBE778DEFD8BA96D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D05D3A4DC15E54B38CB174AB1707F02C /* WCDBOptimizedSQLCipher.release.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap"; - PRODUCT_MODULE_NAME = sqlcipher; - PRODUCT_NAME = sqlcipher; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; 321A2120D400C5B8DC97CEE0924C9F21 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A957AEE9B28E0D13775629CCEB31E52 /* SnapKit.release.xcconfig */; + baseConfigurationReference = F9693744257055D6E8D886301B98967F /* SnapKit.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3305,7 +1956,7 @@ }; 321B5FCE6CECC335057B24FDB5B46280 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4032808F9DA898CCC05CA3A09966607E /* HandyJSON.debug.xcconfig */; + baseConfigurationReference = 537BE90B32A5F1814137F702A3A820F6 /* HandyJSON.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3335,7 +1986,7 @@ }; 3292EE6C81F9FE9F9553CBF573BEF780 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7C5723CCC9FB17ECAE18AE1F0A10DC5C /* BTPrint.release.xcconfig */; + baseConfigurationReference = 12D66D4EBB5005BCB197AA15A08144D1 /* BTPrint.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3368,7 +2019,7 @@ }; 4C547A47042371DAB0F0CDE4F249C217 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C538963150450AD6377ACBE6ECAB0F31 /* BTPrint.debug.xcconfig */; + baseConfigurationReference = 1EE51CB52688C6956C3806BE1352E6A1 /* BTPrint.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3400,7 +2051,7 @@ }; 510C72C4D456365385331898DC3EBDBB /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5D6F6281A81E9332BA17E1E5D6E7AE6D /* BTBubble.release.xcconfig */; + baseConfigurationReference = D8123B10463E4148BBE847951CD834B0 /* BTBubble.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3431,72 +2082,9 @@ }; name = Release; }; - 55405BD8C69303A3292E80140E0366DF /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4EAA4EAE56C6CAB52B38138385B834F9 /* WCDB.swift.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/WCDB.swift/WCDB.swift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/WCDB.swift/WCDB.swift-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/WCDB.swift/WCDB.swift.modulemap"; - PRODUCT_MODULE_NAME = WCDBSwift; - PRODUCT_NAME = WCDBSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 559B7EF25D91AAD3AFF2356C2DE7C0A4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 87765750E33B18AE518B6F447E6C87ED /* SmartCodable.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SmartCodable/SmartCodable-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SmartCodable/SmartCodable-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SmartCodable/SmartCodable.modulemap"; - PRODUCT_MODULE_NAME = SmartCodable; - PRODUCT_NAME = SmartCodable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; 6688C80B0CBE2F2015FBE8A08157FE38 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC3729C5B5DB3FDFBE89ADB7BC30CFED /* SnapKit.debug.xcconfig */; + baseConfigurationReference = 0EE11E0147F987FD843DF343F4BEF9C5 /* SnapKit.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3526,43 +2114,12 @@ }; name = Debug; }; - 685B72E7F1E38A5AB0798B6D53619F8B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8D7BA7EC0C7015514C5CC8ECA03C5A70 /* WCDB.swift.release.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/WCDB.swift/WCDB.swift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/WCDB.swift/WCDB.swift-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/WCDB.swift/WCDB.swift.modulemap"; - PRODUCT_MODULE_NAME = WCDBSwift; - PRODUCT_NAME = WCDBSwift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 829839F3E71B7C18A93044DCB18078DB /* Release */ = { + 8A9329DF318E9055214266B6150CF86B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 47CA9F565D77284A1A541E3C884B8D9D /* SQLiteRepairKit.release.xcconfig */; + baseConfigurationReference = 4A4DC161ED69D1B1A989E4A6912C7B9A /* SmartCodable.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -3571,18 +2128,18 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/SmartCodable/SmartCodable-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SmartCodable/SmartCodable-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap"; - PRODUCT_MODULE_NAME = sqliterk; - PRODUCT_NAME = sqliterk; + MODULEMAP_FILE = "Target Support Files/SmartCodable/SmartCodable.modulemap"; + PRODUCT_MODULE_NAME = SmartCodable; + PRODUCT_NAME = SmartCodable; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -3590,40 +2147,6 @@ }; name = Release; }; - 833F4109C822A8197E2D2326066F4BF9 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CF572B5B26ACF0A775C07589992A5507 /* Pods-SmartCodable_Example.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3690,39 +2213,6 @@ }; name = Debug; }; - 9703914E5D678BEA7F46E25131E1F0ED /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9E36FB803EEC5440AF34F62163B0EDD6 /* SmartCodable.release.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SmartCodable/SmartCodable-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SmartCodable/SmartCodable-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SmartCodable/SmartCodable.modulemap"; - PRODUCT_MODULE_NAME = SmartCodable; - PRODUCT_NAME = SmartCodable; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; 9E406C6AAF85E580207CD97B0044DEAB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3785,9 +2275,44 @@ }; name = Release; }; + AE9192EF60F56396CB0E5F056ECEA21A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6170F13C22D7194151A678E232C31D12 /* Pods-SmartCodable_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; B67EE1E73E10D6FCF6FB371FBD852B85 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 65425402E91EFABF55F0BF3523CE117D /* CleanJSON.debug.xcconfig */; + baseConfigurationReference = 0F6C61A3718CAD5B727FA89E9A50D662 /* CleanJSON.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3818,7 +2343,7 @@ }; BAFE7E7CACC5C2A318C6A56539AD9FB5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D9E3BCE9634968B8A180F21A6AD2D46D /* BTBubble.debug.xcconfig */; + baseConfigurationReference = 4FD9F7D2497A25B05DF82AF7F12F84DF /* BTBubble.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -3848,9 +2373,9 @@ }; name = Debug; }; - E09D8A7E129A92506EAB57507A6396CC /* Debug */ = { + D04725AFC04B7B768953D45606463E8B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 36EE49CE4B82B9346139D56A516D1DB0 /* Pods-SmartCodable_Tests.debug.xcconfig */; + baseConfigurationReference = CF572B5B26ACF0A775C07589992A5507 /* Pods-SmartCodable_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -3863,12 +2388,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -3882,11 +2407,13 @@ }; name = Debug; }; - E940F5C3C750E087819B63DB905E7413 /* Debug */ = { + E09D8A7E129A92506EAB57507A6396CC /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 370B85F293D8CDDA899A559DE09A8A3E /* SQLiteRepairKit.debug.xcconfig */; + baseConfigurationReference = 36EE49CE4B82B9346139D56A516D1DB0 /* Pods-SmartCodable_Tests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -3895,18 +2422,19 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap"; - PRODUCT_MODULE_NAME = sqliterk; - PRODUCT_NAME = sqliterk; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -3950,7 +2478,7 @@ }; F5E44DDE34049B46EE697B0F57D32A4D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F5F4960C860E51A6192EB670A1528988 /* CleanJSON.release.xcconfig */; + baseConfigurationReference = C548E3997850B2E10E6E8D21CACB81A3 /* CleanJSON.release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -3992,20 +2520,20 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 2AF085A0B480398B9D3367C15D32863B /* Build configuration list for PBXNativeTarget "SmartCodable" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */, - 9E406C6AAF85E580207CD97B0044DEAB /* Release */, + 0ADE2129E118C010761FBB9D2337D627 /* Debug */, + 8A9329DF318E9055214266B6150CF86B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4DCF6E1F842BD49DDCD5581FD4574A3F /* Build configuration list for PBXNativeTarget "SmartCodable" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 559B7EF25D91AAD3AFF2356C2DE7C0A4 /* Debug */, - 9703914E5D678BEA7F46E25131E1F0ED /* Release */, + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */, + 9E406C6AAF85E580207CD97B0044DEAB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4037,42 +2565,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9A610C44286ED4C638C6B1CCF09426DB /* Build configuration list for PBXNativeTarget "WCDB.swift" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 55405BD8C69303A3292E80140E0366DF /* Debug */, - 685B72E7F1E38A5AB0798B6D53619F8B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9E702437A4BF298D70F6D6B0ECE32307 /* Build configuration list for PBXNativeTarget "Pods-SmartCodable_Example" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 833F4109C822A8197E2D2326066F4BF9 /* Debug */, - 14DC611A6D2A41704EA1E9C1A32E273B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - BA746E6B99FD9FFB73AC7236870D7DF5 /* Build configuration list for PBXNativeTarget "SQLiteRepairKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E940F5C3C750E087819B63DB905E7413 /* Debug */, - 829839F3E71B7C18A93044DCB18078DB /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C104640870A0FD010B2F89DD2D2CEF43 /* Build configuration list for PBXNativeTarget "WCDBOptimizedSQLCipher" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 28FC5F8B4C8EA087472687C5057C6D66 /* Debug */, - 30B5C0533BF877BCCBE778DEFD8BA96D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; D7119D7A8BDBCCBABD7051B90C53F405 /* Build configuration list for PBXNativeTarget "BTPrint" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4091,6 +2583,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + EEFE656F00195B2CDB67EF4B5BA1AB91 /* Build configuration list for PBXNativeTarget "Pods-SmartCodable_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D04725AFC04B7B768953D45606463E8B /* Debug */, + AE9192EF60F56396CB0E5F056ECEA21A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F6D56E37AAEDB75FE1E0036923FE6A5D /* Build configuration list for PBXNativeTarget "CleanJSON" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Example/Pods/SQLiteRepairKit/LICENSE b/Example/Pods/SQLiteRepairKit/LICENSE deleted file mode 100644 index 6327a273..00000000 --- a/Example/Pods/SQLiteRepairKit/LICENSE +++ /dev/null @@ -1,415 +0,0 @@ -Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. diff --git a/Example/Pods/SQLiteRepairKit/README.md b/Example/Pods/SQLiteRepairKit/README.md deleted file mode 100644 index e52a21c4..00000000 --- a/Example/Pods/SQLiteRepairKit/README.md +++ /dev/null @@ -1,287 +0,0 @@ -# WCDB - -[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/wcdb/pulls) -[![Release Version](https://img.shields.io/badge/release-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/releases) -[![WeChat Approved iOS](https://img.shields.io/badge/Wechat_Approved_iOS-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/blob/master/README.md#wcdb-for-iosmacos) -[![WeChat Approved Android](https://img.shields.io/badge/Wechat_Approved_Android-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/blob/master/README.md#wcdb-for-android) -[![Platform](https://img.shields.io/badge/Platform-%20iOS%20%7C%20macOS%20%7C%20Android-brightgreen.svg)](https://github.com/Tencent/wcdb/wiki) - -中文版本请参看[这里][wcdb-wiki] - -WCDB is an **efficient**, **complete**, **easy-to-use** mobile database framework used in the WeChat application. It's currently available on iOS, macOS and Android. - -# WCDB for iOS/macOS - -## Features - -* **Easy-to-use**. Through WCDB, you can get objects from database in one line code. - - * **WINQ** (WCDB language integrated query): WINQ is a native data querying capability which frees developers from writing glue code to concatenate SQL query strings. - - * **ORM** (Object Relational Mapping): WCDB provides a flexible, easy-to-use ORM for creating tables, indices and constraints, as well as CRUD through ObjC objects. - - ```objective-c - [database getObjectsOfClass:WCTSampleConvenient.class - fromTable:tableName - where:WCTSampleConvenient.intValue>=10 - limit:20]; - ``` - -* **Efficient**. Through the framework layer and sqlcipher source optimization, WCDB have more efficient performance. - - * **Multi-threaded concurrency**: WCDB supports concurrent read-read and read-write access via connection pooling. - * **Batch Write Performance Test**. - ![](https://raw.githubusercontent.com/wiki/Tencent/wcdb/assets/benchmark/baseline_batch_write.png) - For more benchmark data, please refer to [our benchmark][Benchmark-iOS]. - -* **Complete**. - - * **Encryption Support**: WCDB supports database encryption via [SQLCipher][sqlcipher]. - * **Corruption recovery**: WCDB provides a built-in repair kit for database corruption recovery. - * **Anti-injection**: WCDB provides a built-in protection from SQL injection. - -## Getting Started - -### Prerequisites - -* Apps using WCDB can target: iOS 7 or later, macOS 10.9 or later. -* Xcode 8.0 or later required. -* Objective-C++ required. - -### Installation - -* **Via Cocoapods:** - 1. Install [CocoaPods.](https://guides.cocoapods.org/using/getting-started.html) - 2. Run `pod repo update` to make CocoaPods aware of the latest available WCDB versions. - 3. In your Podfile, add `pod 'WCDB'` to your app target. - 4. From the command line, run `pod install`. - 5. Use the `.xcworkspace` file generated by CocoaPods to work on your project. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Carthage:** - 1. Install [Carthage][install-carthage]. - 2. Add `github "Tencent/WCDB"` to your Cartfile. - 3. Run `carthage update`. - 4. Drag `WCDB.framework` from the appropriate platform directory in `Carthage/Build/` to the `Linked Binary and Libraries` section of your Xcode project’s `Build Phases` settings. - 5. On your application targets' `Build Phases` settings tab, click the "+" icon and choose `New Run Script Phase`. Create a Run Script with `carthage copy-frameworks` and add the paths to the frameworks under `Input Files`: `$(SRCROOT)/Carthage/Build/iOS/WCDB.framework` or `$(SRCROOT)/Carthage/Build/Mac/WCDB.framework`. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Dynamic Framework**: - **Note that Dynamic frameworks are not compatible with iOS 7. See “Static Framework” for iOS 7 support.** - 1. Getting source code from git repository and update the submodule of sqlcipher. - - `git clone https://github.com/Tencent/wcdb.git` - - `cd wcdb` - - `git submodule update --init sqlcipher ` - 2. Drag `WCDB.xcodeproj` in `wcdb/apple/` into your project. - 3. Add `WCDB.framework` to the `Enbedded Binaries` section of your Xcode project's `General settings`. **Note that there are two frameworks here and the dynamic one should be chosen. You can check it at `Build Phases`->`Target Dependencies`. The right one is `WCDB` while `WCDB iOS Static is used for static lib.** - 4. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 5. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Static Framework:** - 1. Getting source code from git repository and update the submodule of sqlcipher. - - `git clone https://github.com/Tencent/wcdb.git` - - `cd wcdb` - - `git submodule update --init sqlcipher ` - 2. Drag `WCDB.xcodeproj` in `wcdb/apple/` into your project. - 3. Add `WCDB iOS Static` to the `Target Dependencies` section of your Xcode project's `Build Phases` settings. - 4. Add `WCDB.framework`, `libz.tbd` to the `Linked Binary and Libraries` section of your Xcode project's `Build Phases` settings. Note that there are two `WCDB.framework`, you should choose the one from `WCDB iOS Static` target. - 5. Add `-all_load` and `-ObjC` to the `Other Linker Flags` section of your Xcode project's `Build Settings`. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** - -## Tutorials - -Tutorials can be found [here][iOS-tutorial]. - -## Documentations - -* Documentations can be found on [our Wiki][wcdb-wiki]. -* API references for iOS/macOS can be found [here][wcdb-docs-ios]. -* Performance data can be found on [our benchmark][Benchmark-iOS]. - -# WCDB for Android - -## Features - -* Database encryption via [SQLCipher][sqlcipher]. -* ORM/persistence solution via [Room][room] from Android Architecture Components. -* Concurrent access via connection pooling from modern Android framework. -* Repair toolkit for database corruption recovery. -* Database backup and recovery utility optimized for small backup size. -* Log redirection and various tracing facilities. -* API 14 (Android 4.0) and above are supported. - -## Getting Started - -To include WCDB to your project, choose either way: import via Maven or via AAR package. - -### Import via Maven - -To import WCDB via Maven repositories, add the following lines to `build.gradle` on your -app module: - -```gradle -dependencies { - compile 'com.tencent.wcdb:wcdb-android:1.0.8' - // Replace "1.0.8" to any available version. -} -``` - -This will cause Gradle to download AAR package from JCenter while building your application. - -If you want to use Room persistence library, you need to add the Google Maven repository to -`build.gradle` to your **root project**. - -```gradle -allprojects { - repositories { - jcenter() - google() // Add this line - } -} -``` - -Also add dependencies to module `build.gradle`. - -```gradle -dependencies { - compile 'com.tencent.wcdb:room:1.0.8' - // Replace "1.0.8" to any available version. - - annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' - // Don't forget to include Room annotation compiler from Google. -} -``` - -### Import Prebuilt AAR Package - -   1. **Download AAR package from release page.** -   2. **Import the AAR as new module.** In Android Studio, select `File -> New -> New Module...` menu and choose `"Import JAR/AAR Package"`. -   3. **Add a dependency on the new module.** This can be done using `File -> Project Structure...` in Android Studio, or by adding following code to application's `build.gradle`: -```gradle -dependencies { - // Change "wcdb" to the actual module name specified in step 2. - compile project(':wcdb') -} -``` - -### Migrate from Plain-text SQLite Databases - -WCDB has interfaces very similar to Android SQLite Database APIs. To migrate you application from -AOSP API, change import path from `android.database.*` to `com.tencent.wcdb.*`, and -`android.database.sqlite.*` to `com.tencent.wcdb.database.*`. After import path update, -your application links to WCDB instead of AOSP API. - -To open or create an encrypted database, use with-password versions of -`SQLiteDatabase.openOrCreateDatabase()`, `SQLiteOpenHelper.getWritableDatabase()`, -or `Context.openOrCreateDatabase()`. - -*Note: WCDB uses `byte[]` for password instead of `String` in SQLCipher Android Binding.* - -```java -String password = "MyPassword"; -SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("/path/to/database", password.getBytes(), - null, null); -``` - -See `sample-encryptdb` for sample for transferring data between plain-text and encrypted -databases. - -### Use WCDB with Room - -To use WCDB with Room library, follow the [Room instructions][room]. The only code to change -is specifying `WCDBOpenHelperFactory` when getting instance of the database. - -```java -SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec() - .setPageSize(4096) - .setKDFIteration(64000); - -WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory() - .passphrase("passphrase".getBytes()) // passphrase to the database, remove this line for plain-text - .cipherSpec(cipherSpec) // cipher to use, remove for default settings - .writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed - .asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed - -AppDatabase db = Room.databaseBuilder(this, AppDatabase.class, "app-db") - .allowMainThreadQueries() - .openHelperFactory(factory) // specify WCDBOpenHelperFactory when opening database - .build(); -``` - -See `sample-persistence` for samples using Room library with WCDB. -See `sample-room-with-a-view` for samples using Room library with WCDB and other architecture components from Google. - -> `sample-room-with-a-view` comes from Google's CodeLabs with modification of just a few rows. Search for *\[WCDB\]* keyword for the modification. -> -> See [here][room-codelabs] for the original tutorial. - -### Corruption Recovery - -See `sample-repairdb` for instructions how to recover corrupted databases using `RepairKit`. - -### Redirect Log Output - -By default, WCDB prints its log message to system logcat. You may want to change this -behavior in order to, for example, save logs for troubleshooting. WCDB can redirect -all of its log outputs to user-defined routine using `Log.setLogger(LogCallback)` -method. - -## Build from Sources - -### Build WCDB Android with Prebuilt Dependencies - -WCDB itself can be built apart from its dependencies using Gradle or Android Studio. -To build WCDB Android library, run Gradle on `android` directory: - -```bash -$ cd android -$ ./gradlew build -``` - -Building WCDB requires Android NDK installed. If Gradle failed to find your SDK and/or -NDK, you may need to create a file named `local.properties` on the `android` directory -with content: - -``` -sdk.dir=path/to/sdk -ndk.dir=path/to/ndk -``` - -Android Studio will do this for you when the project is imported. - -### Build Dependencies from Sources - -WCDB depends on OpenSSL crypto library and SQLCipher. You can rebuild all dependencies -if you wish. In this case, a working C compiler on the host system, Perl 5, Tcl and a -bash environment is needed to be installed on your system. - -To build dependencies, checkout all submodules, set `ANDROID_NDK_ROOT` environment -variable to your NDK path, then run `build-depends-android.sh`: - -```bash -$ export ANDROID_NDK_ROOT=/path/to/ndk -$ ./build-depends-android.sh -``` - -This will build OpenSSL crypto library and generate SQLCipher amalgamation sources -and place them to proper locations suitable for WCDB library building. - -## Documentations - -* Documentations can be found on [our Wiki][wcdb-wiki]. -* API references for Android can be found [here][wcdb-docs-android]. - -## Contributing - -If you are interested in contributing, check out the [CONTRIBUTING.md], also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). - -[install-carthage]: https://github.com/Carthage/Carthage#installing-carthage -[wcdb-wiki]: https://github.com/Tencent/wcdb/wiki -[wcdb-docs-ios]: https://tencent.github.io/wcdb/references/ios/index.html -[wcdb-docs-android]: https://tencent.github.io/wcdb/references/android/index.html -[sqlcipher]: https://github.com/sqlcipher/sqlcipher -[room]: https://developer.android.com/topic/libraries/architecture/room -[room-codelabs]: https://codelabs.developers.google.com/codelabs/android-room-with-a-view -[iOS-tutorial]: https://github.com/Tencent/wcdb/wiki/iOS-macOS-Tutorial -[Benchmark-iOS]: https://github.com/Tencent/wcdb/wiki/WCDB-iOS-benchmark - diff --git a/Example/Pods/SQLiteRepairKit/repair/SQLiteRepairKit.h b/Example/Pods/SQLiteRepairKit/repair/SQLiteRepairKit.h deleted file mode 100644 index 15452595..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/SQLiteRepairKit.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 SQLiteRepairKit_h -#define SQLiteRepairKit_h - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct sqliterk sqliterk; -typedef struct sqliterk_table sqliterk_table; -typedef struct sqliterk_column sqliterk_column; - -typedef struct sqliterk_notify sqliterk_notify; -struct sqliterk_notify { - void (*onBeginParseTable)(sqliterk *rk, sqliterk_table *table); - // Only a column that make sense will trigger this callback, - // which is the column in a non-system table or the "sqlite_master" - // return SQLITERK_OK to tell sqliterk that you already know that - // meaning of this column - int (*onParseColumn)(sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column); - void (*onEndParseTable)(sqliterk *rk, sqliterk_table *table); - void (*didParsePage)(sqliterk *rk, int pageno); -}; -int sqliterk_register_notify(sqliterk *rk, sqliterk_notify notify); - -typedef struct sqliterk_cipher_conf { - const void *key; - int key_len; - int page_size; - int kdf_iter; - int use_hmac; - const unsigned char *kdf_salt; -} sqliterk_cipher_conf; - -void sqliterk_cipher_conf_set_key(sqliterk_cipher_conf *conf, const void* key, int key_len); - -typedef struct sqlite3 sqlite3; -typedef struct sqliterk_master_info sqliterk_master_info; - -#define SQLITERK_OUTPUT_NO_CREATE_TABLES 0x0001 -#define SQLITERK_OUTPUT_ALL_TABLES 0x0002 -#define SQLITERK_OUTPUT_CHECK_TABLE_COLUMNS 0x0004 - -int sqliterk_open(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk **rk); -int sqliterk_parse(sqliterk *rk); -int sqliterk_parse_page(sqliterk *rk, int pageno); -int sqliterk_parse_master(sqliterk *rk); -int sqliterk_close(sqliterk *rk); -void *sqliterk_get_user_info(sqliterk *rk); -void sqliterk_set_user_info(sqliterk *rk, void *userInfo); -void sqliterk_set_recursive(sqliterk *rk, int recursive); - -int sqliterk_output(sqliterk *rk, - sqlite3 *db, - sqliterk_master_info *master, - unsigned int flags); -int sqliterk_output_cb(sqliterk *rk, - sqlite3 *db, - sqliterk_master_info *master, - unsigned int flags, - int (*callback)(void *user, - sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column), - void *user); -void sqliterk_cancel(sqliterk *rk); -int sqliterk_make_master(const char **tables, - int num_tables, - sqliterk_master_info **out_master); -int sqliterk_save_master(sqlite3 *db, - const char *path, - const void *key, - int key_len); -int sqliterk_load_master(const char *path, - const void *key, - int key_len, - const char **tables, - int num_tables, - sqliterk_master_info **out_master, - unsigned char *out_kdf_salt); -void sqliterk_free_master(sqliterk_master_info *master); - -// A database may have many kind of tables or indexes, such as a customized -// index or a system-level table and so on. But you should be only concern -// about the listed types below. -// Since the system-level tables or indexes is generated. And you do know -// the index of a certain table (you make this table). -typedef enum { - sqliterk_type_index = -2, - sqliterk_type_table = -1, - sqliterk_type_unknown = 0, - sqliterk_type_sequence = 1, - sqliterk_type_autoindex = 2, - sqliterk_type_stat = 3, - sqliterk_type_master = 4, -} sqliterk_type; - -// This method may return NULL since SQLiteRepairKir may not understand -// a corrupted b-tree. -const char *sqliterk_table_name(sqliterk_table *table); -sqliterk_type sqliterk_table_type(sqliterk_table *table); -int sqliterk_table_root(sqliterk_table *table); -void sqliterk_table_set_user_info(sqliterk_table *table, void *userInfo); -void *sqliterk_table_get_user_info(sqliterk_table *table); - -typedef enum { - sqliterk_value_type_null, - sqliterk_value_type_integer, - sqliterk_value_type_number, - sqliterk_value_type_text, - sqliterk_value_type_binary, -} sqliterk_value_type; - -int sqliterk_column_count(sqliterk_column *column); -sqliterk_value_type sqliterk_column_type(sqliterk_column *column, int index); -int sqliterk_column_integer(sqliterk_column *column, int index); -int64_t sqliterk_column_integer64(sqliterk_column *column, int index); -double sqliterk_column_number(sqliterk_column *column, int index); -const char *sqliterk_column_text(sqliterk_column *column, int index); -const void *sqliterk_column_binary(sqliterk_column *column, int index); -int sqliterk_column_bytes(sqliterk_column *column, int index); -int64_t sqliterk_column_rowid(sqliterk_column *column); - -#define SQLITERK_INTEGRITY_HEADER 0x0001 -#define SQLITERK_INTEGRITY_DATA 0x0002 -#define SQLITERK_INTEGRITY_KDF_SALT 0x0004 - -int sqliterk_parsed_page_count(sqliterk *rk); -int sqliterk_valid_page_count(sqliterk *rk); -int sqliterk_page_count(sqliterk *rk); -unsigned int sqliterk_integrity(sqliterk *rk); - -typedef enum { - sqliterk_loglevel_debug, - sqliterk_loglevel_warning, - sqliterk_loglevel_error, - sqliterk_loglevel_info, -} sqliterk_loglevel; - -typedef struct sqliterk_os sqliterk_os; -struct sqliterk_os { - void (*xLog)(sqliterk_loglevel level, int result, const char *msg); - //TODO -}; -int sqliterk_register(sqliterk_os os); - -#define SQLITERK_OK 0 -#define SQLITERK_CANTOPEN 1 -#define SQLITERK_MISUSE 2 -#define SQLITERK_IOERR 3 -#define SQLITERK_NOMEM 4 -#define SQLITERK_SHORT_READ 5 -#define SQLITERK_DAMAGED 6 -#define SQLITERK_DISCARD 7 -#define SQLITERK_CANCELLED 8 -#define SQLITERK_IGNORE 100 -const char *sqliterk_description(int result); - -#ifndef SQLITRK_CONFIG_DEFAULT_PAGESIZE -#define SQLITRK_CONFIG_DEFAULT_PAGESIZE 4096 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SQLiteRepairKit_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk.c deleted file mode 100644 index d738b81f..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk.h" -#include "SQLiteRepairKit.h" -#include "sqliterk_btree.h" -#include "sqliterk_column.h" -#include "sqliterk_os.h" -#include "sqliterk_pager.h" -#include "sqliterk_util.h" -#include "sqliterk_values.h" -#include - -struct sqliterk { - sqliterk_pager *pager; - sqliterk_btree_notify listen; - sqliterk_notify notify; - void *userInfo; - char recursive; -}; - -//declaration -static void sqliterkNotify_onBeginParseBtree(sqliterk *rk, - sqliterk_btree *btree); -static void -sqliterkNotify_onEndParseBtree(sqliterk *rk, sqliterk_btree *btree, int result); -static int sqliterkNotify_onParseColumn(sqliterk *rk, - sqliterk_btree *btree, - sqliterk_page *page, - sqliterk_column *column); -static int sqliterkNotify_onBeginParsePage(sqliterk *rk, - sqliterk_btree *btree, - int pageno); -static void sqliterkNotify_onEndParsePage(sqliterk *rk, - sqliterk_btree *btree, - int pageno, - int result); -static int sqliterkParseBtree(sqliterk *rk, sqliterk_btree *btree); - -int sqliterkOpen(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk **rk) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk *therk = sqliterkOSMalloc(sizeof(sqliterk)); - if (!therk) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required: %zu bytes", - sizeof(sqliterk)); - goto sqliterkOpen_Failed; - } - - rc = sqliterkPagerOpen(path, cipher, &therk->pager); - if (rc != SQLITERK_OK) { - goto sqliterkOpen_Failed; - } - - therk->listen.onBeginParsePage = sqliterkNotify_onBeginParsePage; - therk->listen.onEndParsePage = sqliterkNotify_onEndParsePage; - therk->listen.onBeginParseBtree = sqliterkNotify_onBeginParseBtree; - therk->listen.onEndParseBtree = sqliterkNotify_onEndParseBtree; - therk->listen.onParseColumn = sqliterkNotify_onParseColumn; - therk->recursive = 1; - - *rk = therk; - sqliterkOSInfo(SQLITERK_OK, "RepairKit on '%s' opened, %s.", path, - cipher ? "encrypted" : "plain-text"); - return SQLITERK_OK; - -sqliterkOpen_Failed: - if (therk) { - sqliterkClose(therk); - } - *rk = NULL; - return rc; -} - -void sqliterk_set_recursive(sqliterk *rk, int recursive) -{ - rk->recursive = (char) recursive; -} - -int sqliterkParse(sqliterk *rk) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - - int i; - for (i = 0; i < sqliterkPagerGetPageCount(rk->pager); i++) { - int pageno = i + 1; - sqliterkParsePage(rk, pageno); - } - return SQLITERK_OK; -} - -int sqliterkParsePage(sqliterk *rk, int pageno) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - if (sqliterkPagerGetStatus(rk->pager, pageno) != - sqliterk_status_unchecked) { - return SQLITERK_OK; - } - int rc = SQLITERK_OK; - sqliterk_btree *btree = NULL; - rc = sqliterkBtreeOpen(rk, rk->pager, pageno, &btree); - if (rc != SQLITERK_OK) { - goto sqliterkParsePage_End; - } - rc = sqliterkParseBtree(rk, btree); -sqliterkParsePage_End: - if (btree) { - sqliterkBtreeClose(btree); - } - return rc; -} - -static int sqliterkParseBtree(sqliterk *rk, sqliterk_btree *btree) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - sqliterk_page *page = sqliterkBtreeGetRootPage(btree); - int pageno = sqliterkPageGetPageno(page); - if (!page || sqliterkPagerIsPagenoValid(rk->pager, pageno) != SQLITERK_OK) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterkBtreeSetNotify(btree, &rk->listen); - rc = sqliterkBtreeParse(btree); - return rc; -} - -int sqliterkParseMaster(sqliterk *rk) -{ - // The page 1 is always sqlite_master. See [B-tree Pages] at - // https://www.sqlite.org/fileformat2.html - return sqliterkParsePage(rk, 1); -} - -int sqliterkClose(sqliterk *rk) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - if (rk->pager) { - sqliterkPagerClose(rk->pager); - rk->pager = NULL; - } - sqliterkOSFree(rk); - return SQLITERK_OK; -} - -static void sqliterkNotify_onBeginParseBtree(sqliterk *rk, - sqliterk_btree *btree) -{ - if (rk->notify.onBeginParseTable) { - rk->notify.onBeginParseTable(rk, (sqliterk_table *) btree); - } - sqliterk_page *rootpage = sqliterkBtreeGetRootPage(btree); - sqliterkOSDebug( - SQLITERK_OK, "Parsing B-tree -> [root: %d, name: %s, type: %s]", - sqliterkPageGetPageno(rootpage), sqliterkBtreeGetName(btree), - sqliterkBtreeGetTypeName(sqliterkBtreeGetType(btree))); -} - -static void -sqliterkNotify_onEndParseBtree(sqliterk *rk, sqliterk_btree *btree, int result) -{ - if (rk->notify.onEndParseTable) { - rk->notify.onEndParseTable(rk, (sqliterk_table *) btree); - } -} - -static int sqliterkNotify_onParseColumn(sqliterk *rk, - sqliterk_btree *btree, - sqliterk_page *page, - sqliterk_column *column) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - - int result; - if (rk->notify.onParseColumn) { - result = rk->notify.onParseColumn(rk, (sqliterk_table *) btree, column); - if (result == SQLITERK_CANCELLED) { - return result; - } else if (result != SQLITERK_OK) { - int pageno = sqliterkPageGetPageno(page); - sqliterkPagerSetStatus(rk->pager, pageno, - sqliterk_status_discarded); - sqliterk_values *overflowPages = - sqliterkColumnGetOverflowPages(column); - - int i; - for (i = 0; i < sqliterkValuesGetCount(overflowPages); i++) { - sqliterkPagerSetStatus( - rk->pager, sqliterkValuesGetInteger(overflowPages, i), - sqliterk_status_discarded); - } - } - } else { - result = SQLITERK_OK; - } - - if (sqliterkBtreeGetType(btree) == sqliterk_btree_type_master && - rk->recursive) { - // Recursively decode the page since the mapping of [table]->[rootPageno] is known - sqliterk_values *values = sqliterkColumnGetValues(column); - const char *type = sqliterkValuesGetText(values, 0); - const char *name = sqliterkValuesGetText(values, 1); - int rootPageno = sqliterkValuesGetInteger(values, 3); - int rc = SQLITERK_OK; - if (type && name) { - sqliterk_btree *subbtree; - rc = sqliterkBtreeOpen(rk, rk->pager, rootPageno, &subbtree); - if (rc == SQLITERK_OK) { - if (memcmp("table", type, 5) == 0) { - sqliterkBtreeSetMeta(subbtree, name, - sqliterk_btree_type_table); - } else if (memcmp("index", type, 5) == 0) { - sqliterkBtreeSetMeta(subbtree, name, - sqliterk_btree_type_index); - } else { - sqliterkBtreeSetMeta(subbtree, name, - sqliterk_btree_type_unknown); - } - rc = sqliterkParseBtree(rk, subbtree); - } - if (rc != SQLITERK_OK) { - sqliterk_page *rootpage = sqliterkBtreeGetRootPage(subbtree); - sqliterkOSError( - rc, - "sqliterkNotify_onParseColumn: failed to parse known " - "table with root page no. %d, name %s, type %s", - sqliterkPageGetPageno(rootpage), - sqliterkBtreeGetName(subbtree), - sqliterkBtreeGetTypeName(sqliterkBtreeGetType(subbtree))); - } - if (subbtree) { - sqliterkBtreeClose(subbtree); - } - } - } - - return result; -} - -static int -sqliterkNotify_onBeginParsePage(sqliterk *rk, sqliterk_btree *btree, int pageno) -{ - //sqliterkOSDebug(SQLITERK_OK, "sqliterkNotify_onBeginParsePage: %d", pageno); - if (sqliterkPagerGetStatus(rk->pager, pageno) == sqliterk_status_checking) { - return SQLITERK_MISUSE; - } - sqliterkPagerSetStatus(rk->pager, pageno, sqliterk_status_checking); - return SQLITERK_OK; -} - -static void sqliterkNotify_onEndParsePage(sqliterk *rk, - sqliterk_btree *btree, - int pageno, - int result) -{ - if (!rk) { - return; - } - switch (result) { - case SQLITERK_OK: - sqliterkPagerSetStatus(rk->pager, pageno, sqliterk_status_checked); - break; - case SQLITERK_DAMAGED: - sqliterkPagerSetStatus(rk->pager, pageno, sqliterk_status_damaged); - break; - case SQLITERK_CANCELLED: - sqliterkOSDebug(SQLITERK_CANCELLED, "Cancelled parsing page %d.", - pageno); - break; - default: - sqliterkOSWarning(SQLITERK_MISUSE, - "Cannot parse page %d. Invalid type.", pageno); - sqliterkPagerSetStatus(rk->pager, pageno, sqliterk_status_invalid); - break; - } - //sqliterkOSDebug(result, "sqliterkNotify_onEndParsePage: %d", pageno); - if (rk->notify.didParsePage) { - rk->notify.didParsePage(rk, pageno); - } -} - -int sqliterkSetNotify(sqliterk *rk, sqliterk_notify notify) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - rk->notify = notify; - return SQLITERK_OK; -} - -int sqliterkSetUserInfo(sqliterk *rk, void *userInfo) -{ - if (!rk) { - return SQLITERK_MISUSE; - } - rk->userInfo = userInfo; - return SQLITERK_OK; -} - -void *sqliterkGetUserInfo(sqliterk *rk) -{ - if (!rk) { - return NULL; - } - return rk->userInfo; -} - -int sqliterkGetParsedPageCount(sqliterk *rk) -{ - if (!rk) { - return 0; - } - return sqliterkPagerGetParsedPageCount(rk->pager); -} - -int sqliterkGetValidPageCount(sqliterk *rk) -{ - if (!rk) { - return 0; - } - return sqliterkPagerGetValidPageCount(rk->pager); -} - -int sqliterkGetPageCount(sqliterk *rk) -{ - if (!rk) { - return 0; - } - return sqliterkPagerGetPageCount(rk->pager); -} - -unsigned int sqliterkGetIntegrity(sqliterk *rk) -{ - if (!rk) { - return 0; - } - return sqliterkPagerGetIntegrity(rk->pager); -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk.h deleted file mode 100644 index 5b2a2004..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_h -#define sqliterk_h - -typedef struct sqliterk sqliterk; -typedef struct sqliterk_cipher_conf sqliterk_cipher_conf; -typedef struct sqliterk_notify sqliterk_notify; - -int sqliterkOpen(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk **rk); -int sqliterkParse(sqliterk *rk); -int sqliterkParsePage(sqliterk *rk, int pageno); -int sqliterkParseMaster(sqliterk *rk); -int sqliterkClose(sqliterk *rk); -int sqliterkSetNotify(sqliterk *rk, sqliterk_notify notify); -int sqliterkSetUserInfo(sqliterk *rk, void *userInfo); -void *sqliterkGetUserInfo(sqliterk *rk); - -int sqliterkGetParsedPageCount(sqliterk *rk); -int sqliterkGetValidPageCount(sqliterk *rk); -int sqliterkGetPageCount(sqliterk *rk); -unsigned int sqliterkGetIntegrity(sqliterk *rk); - -#endif /* sqliterk_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_api.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_api.c deleted file mode 100644 index 7f16b1e9..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_api.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "SQLiteRepairKit.h" -#include "sqliterk.h" -#include "sqliterk_btree.h" -#include "sqliterk_column.h" -#include "sqliterk_os.h" -#include "sqliterk_pager.h" -#include "sqliterk_util.h" -#include "sqliterk_values.h" - -int sqliterk_register_notify(sqliterk *rk, sqliterk_notify notify) -{ - return sqliterkSetNotify(rk, notify); -} - -int sqliterk_open(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk **rk) -{ - return sqliterkOpen(path, cipher, rk); -} - -void *sqliterk_user_info(sqliterk *rk) -{ - return sqliterkGetUserInfo(rk); -} - -int sqliterk_parse(sqliterk *rk) -{ - return sqliterkParse(rk); -} - -int sqliterk_parse_page(sqliterk *rk, int pageno) -{ - return sqliterkParsePage(rk, pageno); -} - -int sqliterk_parse_master(sqliterk *rk) -{ - return sqliterkParseMaster(rk); -} - -int sqliterk_close(sqliterk *rk) -{ - return sqliterkClose(rk); -} - -void *sqliterk_get_user_info(sqliterk *rk) -{ - return sqliterkGetUserInfo(rk); -} - -void sqliterk_set_user_info(sqliterk *rk, void *userInfo) -{ - sqliterkSetUserInfo(rk, userInfo); -} - -int sqliterk_column_count(sqliterk_column *column) -{ - return sqliterkValuesGetCount(sqliterkColumnGetValues(column)); -} - -sqliterk_value_type sqliterk_column_type(sqliterk_column *column, int index) -{ - return sqliterkValuesGetType(sqliterkColumnGetValues(column), index); -} - -int sqliterk_column_integer(sqliterk_column *column, int index) -{ - return sqliterkValuesGetInteger(sqliterkColumnGetValues(column), index); -} - -int64_t sqliterk_column_integer64(sqliterk_column *column, int index) -{ - return sqliterkValuesGetInteger64(sqliterkColumnGetValues(column), index); -} - -double sqliterk_column_number(sqliterk_column *column, int index) -{ - return sqliterkValuesGetNumber(sqliterkColumnGetValues(column), index); -} - -const char *sqliterk_column_text(sqliterk_column *column, int index) -{ - return sqliterkValuesGetText(sqliterkColumnGetValues(column), index); -} - -const void *sqliterk_column_binary(sqliterk_column *column, int index) -{ - return sqliterkValuesGetBinary(sqliterkColumnGetValues(column), index); -} - -int sqliterk_column_bytes(sqliterk_column *column, int index) -{ - return sqliterkValuesGetBytes(sqliterkColumnGetValues(column), index); -} - -int64_t sqliterk_column_rowid(sqliterk_column *column) -{ - return sqliterkColumnGetRowId(column); -} - -const char *sqliterk_table_name(sqliterk_table *table) -{ - return sqliterkBtreeGetName((sqliterk_btree *) table); -} - -void sqliterk_table_set_user_info(sqliterk_table *table, void *userInfo) -{ - sqliterkBtreeSetUserInfo((sqliterk_btree *) table, userInfo); -} - -void *sqliterk_table_get_user_info(sqliterk_table *table) -{ - return sqliterkBtreeGetUserInfo((sqliterk_btree *) table); -} - -sqliterk_type sqliterk_table_type(sqliterk_table *table) -{ - return (sqliterk_type) sqliterkBtreeGetType((sqliterk_btree *) table); -} - -int sqliterk_register(sqliterk_os os) -{ - return sqliterkOSRegister(os); -} - -int sqliterk_table_root(sqliterk_table *table) -{ - sqliterk_page *page = sqliterkBtreeGetRootPage((sqliterk_btree *) table); - return sqliterkPageGetPageno(page); -} - -const char *sqliterk_description(int result) -{ - return sqliterkGetResultCodeDescription(result); -} - -int sqliterk_parsed_page_count(sqliterk *rk) -{ - return sqliterkGetParsedPageCount(rk); -} - -int sqliterk_valid_page_count(sqliterk *rk) -{ - return sqliterkGetValidPageCount(rk); -} - -int sqliterk_page_count(sqliterk *rk) -{ - return sqliterkGetPageCount(rk); -} - -unsigned int sqliterk_integrity(sqliterk *rk) -{ - return sqliterkGetIntegrity(rk); -} - -void sqliterk_cipher_conf_set_key(sqliterk_cipher_conf *conf, const void* key, int key_len) -{ - if (conf != NULL) { - conf->key = key; - conf->key_len = key_len; - } -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.c deleted file mode 100644 index 70308488..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_btree.h" -#include "SQLiteRepairKit.h" -#include "sqliterk_column.h" -#include "sqliterk_os.h" -#include "sqliterk_pager.h" -#include "sqliterk_util.h" -#include "sqliterk_values.h" -#include -#include - -// Declarations -static int sqliterkBtreeParsePage(sqliterk_btree *btree, int pageno); -static int sqliterkBtreeParseCell(sqliterk_btree *btree, - sqliterk_page *page, - const int *cellPointerArray, - const int cellsCount); -static int sqliterkBtreeParsePayload(sqliterk_btree *btree, - sqliterk_page *page, - int offset, - int payloadSize, - sqliterk_column *column); -static int sqliterkBtreeGetLengthForSerialType(int serialType); - -struct sqliterk_btree { - sqliterk *rk; - char *name; - sqliterk_btree_type type; - sqliterk_pager *pager; - sqliterk_page *rootpage; - // For leaf-table. See https://www.sqlite.org/fileformat2.html#btree - int maxLocal; - int minLocal; - int maxLeaf; - int minLeaf; - - sqliterk_btree_notify notify; - void *userInfo; -}; - -int sqliterkBtreeOpen(sqliterk *rk, - sqliterk_pager *pager, - int rootPageno, - sqliterk_btree **btree) -{ - if (!pager || !btree) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_btree *theBtree = sqliterkOSMalloc(sizeof(sqliterk_btree)); - if (!theBtree) { - rc = SQLITERK_NOMEM; - goto sqliterkBtreeOpen_Failed; - } - theBtree->pager = pager; - - rc = sqliterkPageAcquire(theBtree->pager, rootPageno, &theBtree->rootpage); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeOpen_Failed; - } - if (rootPageno == 1) { - rc = sqliterkBtreeSetMeta(theBtree, "sqlite_master", - sqliterk_btree_type_master); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeOpen_Failed; - } - } else { - switch (sqliterkPageGetType(theBtree->rootpage)) { - case sqliterk_page_type_interior_index: - case sqliterk_page_type_leaf_index: - theBtree->type = sqliterk_btree_type_index; - break; - case sqliterk_page_type_interior_table: - case sqliterk_page_type_leaf_table: - theBtree->type = sqliterk_btree_type_table; - break; - default: - rc = SQLITERK_DAMAGED; - goto sqliterkBtreeOpen_Failed; - } - } - // Save memory - sqliterkPageClearData(theBtree->rootpage); - - theBtree->maxLocal = - (sqliterkPagerGetUsableSize(theBtree->pager) - 12) * 64 / 255 - 23; - theBtree->minLocal = - (sqliterkPagerGetUsableSize(theBtree->pager) - 12) * 32 / 255 - 23; - theBtree->maxLeaf = sqliterkPagerGetUsableSize(theBtree->pager) - 35; - theBtree->minLeaf = - (sqliterkPagerGetUsableSize(theBtree->pager) - 12) * 32 / 255 - 23; - - theBtree->rk = rk; - - *btree = theBtree; - return SQLITERK_OK; - -sqliterkBtreeOpen_Failed: - if (theBtree) { - sqliterkBtreeClose(theBtree); - } - *btree = NULL; - return rc; -} - -int sqliterkBtreeParse(sqliterk_btree *btree) -{ - if (!btree) { - return SQLITERK_MISUSE; - } - if (btree->notify.onBeginParseBtree) { - btree->notify.onBeginParseBtree(btree->rk, btree); - } - int rc = - sqliterkBtreeParsePage(btree, sqliterkPageGetPageno(btree->rootpage)); - if (btree->notify.onEndParseBtree) { - btree->notify.onEndParseBtree(btree->rk, btree, rc); - } - return rc; -} - -// If the page is an interior-btree, no matter is an interior-table btree -// or an interior-index btree, this function will recursively parse the page -// until it find the leaf page or any error occur. -// A leaf-index btree will only be found but not parse, since its data make -// no sense. -static int sqliterkBtreeParsePage(sqliterk_btree *btree, int pageno) -{ - int i; - - if (!btree || pageno > sqliterkPagerGetPageCount(btree->pager)) { - return SQLITERK_MISUSE; - } - - int rc; - - if (btree->notify.onBeginParsePage) { - rc = btree->notify.onBeginParsePage(btree->rk, btree, pageno); - if (rc != SQLITERK_OK) { - return rc; - } - } - - int *cellPointerArray = NULL; - sqliterk_page *page = NULL; - - // ahead checking type to fast up parsing - rc = sqliterkPageAcquire(btree->pager, pageno, &page); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParsePage_End; - } - sqliterk_page_type type = sqliterkPageGetType(page); - if (type != sqliterk_page_type_interior_index && - type != sqliterk_page_type_interior_table && - type != sqliterk_page_type_leaf_index && - type != sqliterk_page_type_leaf_table) { - rc = sqliterkOSWarning(SQLITERK_DAMAGED, "Page %d has invalid type", - pageno); - goto sqliterkBtreeParsePage_End; - } - - //sqliterkOSDebug(SQLITERK_OK, "Page %d is %s", pageno, sqliterkPageGetTypeName(type)); - - // Parse cell pointer array. For further information, see [cell pointer] - // at https://www.sqlite.org/fileformat2.html#btree - const unsigned char *pagedata = sqliterkPageGetData(page); - int offsetCellPointerArray = - (type == sqliterk_page_type_interior_table) ? 12 : 8; - int cellsCount; - sqliterkParseInt(pagedata, 3 + sqliterkPageHeaderOffset(page), 2, - &cellsCount); - if (cellsCount <= 0 || cellsCount * 2 + offsetCellPointerArray > - sqliterkPagerGetSize(btree->pager)) { - rc = SQLITERK_DAMAGED; - goto sqliterkBtreeParsePage_End; - } - cellPointerArray = sqliterkOSMalloc(sizeof(int) * (cellsCount + 1)); - if (!cellPointerArray) { - rc = SQLITERK_NOMEM; - goto sqliterkBtreeParsePage_End; - } - - for (i = 0; i < cellsCount; i++) { - int cellPointer; - sqliterkParseInt(pagedata, - sqliterkPageHeaderOffset(page) + - offsetCellPointerArray + i * 2, - 2, &cellPointer); - cellPointerArray[i] = cellPointer; - } - - switch (type) { - case sqliterk_page_type_interior_table: - case sqliterk_page_type_interior_index: { - int hasRightMostPageno = - (type == sqliterk_page_type_interior_table); - int pagenosCount = cellsCount + hasRightMostPageno; - int *pagenos = sqliterkOSMalloc(sizeof(int) * (pagenosCount + 1)); - if (!pagenos) { - rc = SQLITERK_NOMEM; - goto sqliterkBtreeParsePage_End; - } - for (i = 0; i < cellsCount; i++) { - sqliterkParseInt(pagedata, cellPointerArray[i], 4, pagenos + i); - } - if (hasRightMostPageno) { - sqliterkParseInt(pagedata, 8, 4, pagenos + cellsCount); - } - // All done for page data. Ahead release the page data to avoid memory overflow - sqliterkOSFree(cellPointerArray); - cellPointerArray = NULL; - sqliterkPageClearData(page); - // Recursively decode the page - for (i = 0; i < pagenosCount; i++) { - if (sqliterkBtreeParsePage(btree, pagenos[i]) == - SQLITERK_CANCELLED) - break; - } - sqliterkOSFree(pagenos); - break; - } - case sqliterk_page_type_leaf_table: - if (sqliterkBtreeIsSystemType(sqliterkBtreeGetType(btree)) && - btree->type != sqliterk_btree_type_master) { - //skip a non-master system table, since its column is generated. - goto sqliterkBtreeParsePage_End; - } - rc = sqliterkBtreeParseCell(btree, page, cellPointerArray, - cellsCount); - break; - case sqliterk_page_type_leaf_index: - // Just skip it since the column in leaf index make no sense. - break; - default: - break; - } - -sqliterkBtreeParsePage_End: - if (cellPointerArray) { - sqliterkOSFree(cellPointerArray); - } - if (btree->notify.onEndParsePage) { - btree->notify.onEndParsePage(btree->rk, btree, pageno, rc); - } - if (page) { - sqliterkPageRelease(page); - } - if (rc != SQLITERK_OK && rc != SQLITERK_CANCELLED) { - sqliterkOSDebug(rc, "Failed to parse page %d.", pageno); - } - return rc; -} - -// Parse the payload data. see [B-tree Cell Format] -// at https://www.sqlite.org/fileformat2.html#btree -static int sqliterkBtreeParseCell(sqliterk_btree *btree, - sqliterk_page *page, - const int *cellPointerArray, - const int cellsCount) -{ - if (!btree || !page || !cellPointerArray || cellsCount < 0) { - return SQLITERK_MISUSE; - } - const unsigned char *pagedata = sqliterkPageGetData(page); - int rc = SQLITERK_OK; - sqliterk_column *column; - rc = sqliterkColumnAlloc(&column); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParsePayload_End; - } - - int i; - for (i = 0; i < cellsCount; i++) { - sqliterkColumnClear(column); - int offset = cellPointerArray[i]; - // Find payload - int payloadSizeLength; - int64_t payloadSize; - rc = sqliterkParseVarint64(pagedata, offset, &payloadSizeLength, - &payloadSize); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParsePayload_End; - } else if (payloadSize > 64 * 1024 * 1024) { - // We assume that payload is at most 64MB. - rc = SQLITERK_DAMAGED; - sqliterkOSDebug(rc, "Invalid payload size: %" PRId64 ".", payloadSize); - goto sqliterkBtreeParsePayload_End; - } - offset += payloadSizeLength; - - int rowidLength; - int64_t rowid; - rc = sqliterkParseVarint64(pagedata, offset, &rowidLength, &rowid); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParsePayload_End; - } - offset += rowidLength; - sqliterkColumnSetRowId(column, rowid); - - rc = - sqliterkBtreeParsePayload(btree, page, offset, payloadSize, column); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParsePayload_End; - } - } -sqliterkBtreeParsePayload_End: - if (column) { - sqliterkColumnFree(column); - } - if (rc != SQLITERK_OK && rc != SQLITERK_CANCELLED) { - sqliterkOSDebug(rc, "Failed to parse payload."); - } - return rc; -} - -// Parse the payload for leaf-table page only. We don't implement the parse -// method for index page, since we are not concerned about the data in an -// index page. See [Record Format] at https://www.sqlite.org/fileformat2.html -static int sqliterkBtreeParsePayload(sqliterk_btree *btree, - sqliterk_page *page, - int offset, - int payloadSize, - sqliterk_column *column) -{ - if (!btree || payloadSize <= 0 || !column) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - unsigned char *payloadData = sqliterkOSMalloc(payloadSize); - if (!payloadData) { - rc = SQLITERK_NOMEM; - goto sqliterkBtreeParseColumn_End; - } - - // Check overflow - int local = 0; - if (payloadSize <= btree->maxLeaf) { - local = payloadSize; - } else { - // Since it is a leaf-table page, the max local should be equal to max leaf - int maxPageLocal = btree->maxLeaf; - int minPageLocal = btree->minLocal; - int surplus = - minPageLocal + (payloadSize - minPageLocal) % - (sqliterkPagerGetUsableSize(btree->pager) - 4); - if (surplus <= maxPageLocal) { - local = surplus; - } else { - local = minPageLocal; - } - } - - // Read data - int payloadPointer = 0; - const unsigned char *pagedata = sqliterkPageGetData(page); - if (offset + local > sqliterkPagerGetSize(btree->pager)) { - rc = SQLITERK_DAMAGED; - goto sqliterkBtreeParseColumn_End; - } - memcpy(payloadData, pagedata + offset, local); - payloadPointer += local; - - if (payloadPointer < payloadSize) { - sqliterk_values *overflowPages = sqliterkColumnGetOverflowPages(column); - int overflowPageno; - const unsigned char *pagedata = sqliterkPageGetData(page); - sqliterkParseInt(pagedata, offset + local, 4, &overflowPageno); - while (sqliterkPagerIsPagenoValid(btree->pager, overflowPageno) == - SQLITERK_OK) { - sqliterkValuesAddInteger(overflowPages, overflowPageno); - if (btree->notify.onBeginParsePage) { - btree->notify.onBeginParsePage(btree->rk, btree, - overflowPageno); - } - sqliterk_page *page; - rc = sqliterkPageAcquireOverflow(btree->pager, overflowPageno, - &page); - if (btree->notify.onEndParsePage) { - btree->notify.onEndParsePage(btree->rk, btree, overflowPageno, - rc); - } - if (rc != SQLITERK_OK) { - break; - } - // Read data - int overflowSize = payloadSize - payloadPointer; - if (overflowSize <= 0) break; - - int maxSize = sqliterkPagerGetUsableSize(btree->pager) - 4; - if (overflowSize > maxSize) { - overflowSize = maxSize; - } - - const unsigned char *pageData = sqliterkPageGetData(page); - memcpy(payloadData + payloadPointer, pageData + 4, overflowSize); - payloadPointer += overflowSize; - // Iterate - sqliterkParseInt(pageData, 0, 4, &overflowPageno); - // Clear - sqliterkPageRelease(page); - } - } - - int columnOffsetValue = 0; - int columnOffsetValueLength = 0; - rc = sqliterkParseVarint(payloadData, 0, &columnOffsetValueLength, - &columnOffsetValue); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParseColumn_End; - } - - int offsetSerialType = columnOffsetValueLength; - int offsetValue = columnOffsetValue; - const int endSerialType = offsetValue; - const int endValue = payloadSize; - - int serialTypeLength = 0; - int serialType = 0; - int valueLength = 0; - - sqliterk_values *values = sqliterkColumnGetValues(column); - while (offsetValue < endValue || offsetSerialType < endSerialType) { - rc = sqliterkParseVarint(payloadData, offsetSerialType, - &serialTypeLength, &serialType); - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParseColumn_End; - } - valueLength = sqliterkBtreeGetLengthForSerialType(serialType); - if (serialType == 0) { - rc = sqliterkValuesAddNull(values); - } else if (serialType < 7) { - int64_t value; - sqliterkParseInt64(payloadData, offsetValue, valueLength, &value); - rc = sqliterkValuesAddInteger64(values, value); - } else if (serialType == 7) { - double value; - sqliterkParseNumber(payloadData, offsetValue, &value); - rc = sqliterkValuesAddNumber(values, value); - } else if (serialType == 8) { - rc = sqliterkValuesAddInteger(values, 0); - } else if (serialType == 9) { - rc = sqliterkValuesAddInteger(values, 1); - } else if (serialType >= 12) { - if (serialType % 2 == 0) { - rc = sqliterkValuesAddBinary(values, payloadData + offsetValue, - valueLength); - } else { - rc = sqliterkValuesAddNoTerminatorText( - values, (const char *) payloadData + offsetValue, - valueLength); - } - } else { - rc = SQLITERK_DAMAGED; - } - if (rc != SQLITERK_OK) { - goto sqliterkBtreeParseColumn_End; - } - offsetValue += valueLength; - offsetSerialType += serialTypeLength; - } - if (offsetSerialType != endSerialType || offsetValue != endValue) { - rc = SQLITERK_DAMAGED; - goto sqliterkBtreeParseColumn_End; - } - -sqliterkBtreeParseColumn_End: - if (rc == SQLITERK_OK && btree->notify.onParseColumn) { - rc = btree->notify.onParseColumn(btree->rk, btree, page, column); - } - if (payloadData) { - sqliterkOSFree(payloadData); - } - return rc; -} - -int sqliterkBtreeClose(sqliterk_btree *btree) -{ - if (!btree) { - return SQLITERK_MISUSE; - } - if (btree->name) { - sqliterkOSFree(btree->name); - btree->name = NULL; - } - if (btree->rootpage) { - sqliterkPageRelease(btree->rootpage); - btree->rootpage = NULL; - } - btree->pager = NULL; - btree->userInfo = NULL; - btree->rk = NULL; - btree->type = 0; - sqliterkOSFree(btree); - return SQLITERK_OK; -} - -int sqliterkBtreeSetMeta(sqliterk_btree *btree, - const char *name, - sqliterk_btree_type type) -{ - if (!btree) { - return SQLITERK_MISUSE; - } - if (btree->name) { - sqliterkOSFree(btree->name); - btree->name = NULL; - } - if (name) { - size_t length = strlen(name); - btree->name = sqliterkOSMalloc(sizeof(char) * (length + 1)); - if (!btree->name) { - return SQLITERK_NOMEM; - } - strncpy(btree->name, name, length); - // If it's a system btree name, then setup its b-tree type. - sqliterk_btree_type i; - for (i = sqliterk_btree_type_system_begin; - i < sqliterk_btree_type_system_end; i++) { - const char *typename = sqliterkBtreeGetTypeName(i); - if (strncmp(btree->name, typename, strlen(typename)) == 0) { - btree->type = i; - break; - } - } - } else { - btree->name = NULL; - } - if (!sqliterkBtreeIsSystemType(btree->type) && - type != sqliterk_btree_type_unknown) { - btree->type = type; - } - return SQLITERK_OK; -} - -const char *sqliterkBtreeGetName(sqliterk_btree *btree) -{ - if (!btree) { - return NULL; - } - return btree->name; -} - -sqliterk_btree_type sqliterkBtreeGetType(sqliterk_btree *btree) -{ - if (!btree) { - return sqliterk_btree_type_unknown; - } - return btree->type; -} - -int sqliterkBtreeSetType(sqliterk_btree *btree, sqliterk_btree_type type) -{ - if (!btree) { - return SQLITERK_MISUSE; - } - if (sqliterkBtreeIsSystemType(btree->type)) { - // You can only set the type manually when the type is not a system type - return SQLITERK_MISUSE; - } - btree->type = type; - return SQLITERK_OK; -} - -int sqliterkBtreeIsSystemType(sqliterk_btree_type type) -{ - if (type >= sqliterk_btree_type_system_begin && - type < sqliterk_btree_type_system_end) { - return 1; - } - return 0; -} - -void sqliterkBtreeSetNotify(sqliterk_btree *btree, - sqliterk_btree_notify *notify) -{ - if (!btree || !notify) { - return; - } - btree->notify = *notify; -} - -void sqliterkBtreeSetUserInfo(sqliterk_btree *btree, void *userInfo) -{ - if (!btree) { - return; - } - btree->userInfo = userInfo; -} - -void *sqliterkBtreeGetUserInfo(sqliterk_btree *btree) -{ - if (!btree) { - return NULL; - } - return btree->userInfo; -} - -sqliterk_page *sqliterkBtreeGetRootPage(sqliterk_btree *btree) -{ - if (!btree) { - return NULL; - } - return btree->rootpage; -} - -const char *sqliterkBtreeGetTypeName(sqliterk_btree_type type) -{ - char *name; - switch (type) { - case sqliterk_btree_type_autoindex: - name = "sqlite_autoindex"; - break; - case sqliterk_btree_type_sequence: - name = "sqlite_sequence"; - break; - case sqliterk_btree_type_stat: - name = "sqlite_stat"; - break; - case sqliterk_btree_type_master: - name = "sqlite_master"; - break; - case sqliterk_btree_type_table: - name = "table"; - break; - case sqliterk_btree_type_index: - name = "index"; - break; - default: - name = "unknown"; - break; - } - return name; -} - -// See [Serial Type Codes Of The Record Format] -// at https://www.sqlite.org/fileformat2.html -static int sqliterkBtreeGetLengthForSerialType(int serialType) -{ - if (serialType < 0) { - return 0; - } - static int sqliterk_btree_serialtype_fixlengths[12] = {0, 1, 2, 3, 4, 6, - 8, 8, 0, 0, 0, 0}; - if (serialType < 12) { - return sqliterk_btree_serialtype_fixlengths[serialType]; - } - return (serialType - 12 - serialType % 2) / 2; -} \ No newline at end of file diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.h deleted file mode 100644 index 7b9a9352..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_btree.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_btree_h -#define sqliterk_btree_h - -// About sqliterk_btree, see https://www.sqlite.org/fileformat2.html#btree -typedef struct sqliterk_btree sqliterk_btree; -typedef struct sqliterk_pager sqliterk_pager; -typedef struct sqliterk_values sqliterk_values; -typedef struct sqliterk_column sqliterk_column; -typedef struct sqliterk_page sqliterk_page; -typedef struct sqliterk sqliterk; -typedef struct sqliterk_btree_notify sqliterk_btree_notify; - -typedef enum { - sqliterk_btree_type_index = -2, - sqliterk_btree_type_table = -1, - sqliterk_btree_type_unknown = 0, - // About SQLite reserved btree, see [Storage Of The SQL Database Schema] - // chapter at https://www.sqlite.org/fileformat2.html#Schema - sqliterk_btree_type_system_begin = 1, - sqliterk_btree_type_sequence = 1, - sqliterk_btree_type_autoindex = 2, - sqliterk_btree_type_stat = 3, - sqliterk_btree_type_master = 4, - sqliterk_btree_type_system_end = 5, -} sqliterk_btree_type; - -struct sqliterk_btree_notify { - void (*onBeginParseBtree)(sqliterk *rk, sqliterk_btree *btree); - void (*onEndParseBtree)(sqliterk *rk, sqliterk_btree *btree, int result); - int (*onParseColumn)(sqliterk *rk, - sqliterk_btree *btree, - sqliterk_page *page, - sqliterk_column *column); - - // return SQLITE_OK to continue parsing the page. All other return - // value will skip the parsing phase of this page. - int (*onBeginParsePage)(sqliterk *rk, sqliterk_btree *btree, int pageno); - - void (*onEndParsePage)(sqliterk *rk, - sqliterk_btree *btree, - int pageno, - int result); -}; - -int sqliterkBtreeOpen(sqliterk *rk, - sqliterk_pager *pager, - int rootPageno, - sqliterk_btree **btree); -int sqliterkBtreeParse(sqliterk_btree *btree); -int sqliterkBtreeClose(sqliterk_btree *btree); - -int sqliterkBtreeSetMeta(sqliterk_btree *btree, - const char *name, - sqliterk_btree_type type); -const char *sqliterkBtreeGetName(sqliterk_btree *btree); -sqliterk_btree_type sqliterkBtreeGetType(sqliterk_btree *btree); -int sqliterkBtreeIsSystemType(sqliterk_btree_type type); -sqliterk_page *sqliterkBtreeGetRootPage(sqliterk_btree *btree); - -void sqliterkBtreeSetNotify(sqliterk_btree *btree, - sqliterk_btree_notify *notify); -void sqliterkBtreeSetUserInfo(sqliterk_btree *btree, void *userInfo); -void *sqliterkBtreeGetUserInfo(sqliterk_btree *btree); -const char *sqliterkBtreeGetTypeName(sqliterk_btree_type type); - -#endif /* sqliterk_btree_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.c deleted file mode 100644 index 1b1d52e2..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_column.h" -#include "sqliterk_os.h" - -struct sqliterk_column { - int64_t rowid; - sqliterk_values *values; - sqliterk_values *overflowPages; -}; - -int sqliterkColumnAlloc(sqliterk_column **column) -{ - if (!column) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_column *theColumn = sqliterkOSMalloc(sizeof(sqliterk_column)); - if (!theColumn) { - rc = SQLITERK_NOMEM; - goto sqliterkColumnAlloc_Failed; - } - rc = sqliterkValuesAlloc(&theColumn->values); - if (rc != SQLITERK_OK) { - goto sqliterkColumnAlloc_Failed; - } - rc = sqliterkValuesAlloc(&theColumn->overflowPages); - if (rc != SQLITERK_OK) { - goto sqliterkColumnAlloc_Failed; - } - *column = theColumn; - return SQLITERK_OK; - -sqliterkColumnAlloc_Failed: - if (theColumn) { - sqliterkColumnFree(theColumn); - } - *column = NULL; - return rc; -} - -int sqliterkColumnFree(sqliterk_column *column) -{ - if (!column) { - return SQLITERK_MISUSE; - } - if (column->overflowPages) { - sqliterkValuesFree(column->overflowPages); - } - if (column->values) { - sqliterkValuesFree(column->values); - } - sqliterkOSFree(column); - return SQLITERK_OK; -} - -sqliterk_values *sqliterkColumnGetValues(sqliterk_column *column) -{ - if (!column) { - return NULL; - } - return column->values; -} - -void sqliterkColumnSetRowId(sqliterk_column *column, int64_t rowid) -{ - if (column) { - column->rowid = rowid; - } -} - -int64_t sqliterkColumnGetRowId(sqliterk_column *column) -{ - if (!column) { - return 0; - } - return column->rowid; -} - -sqliterk_values *sqliterkColumnGetOverflowPages(sqliterk_column *column) -{ - if (!column) { - return NULL; - } - return column->overflowPages; -} - -int sqliterkColumnClear(sqliterk_column *column) -{ - if (!column) { - return SQLITERK_MISUSE; - } - column->rowid = 0; - sqliterkValuesClear(column->overflowPages); - sqliterkValuesClear(column->values); - return SQLITERK_OK; -} \ No newline at end of file diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.h deleted file mode 100644 index acb3d4b7..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_column.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_column_h -#define sqliterk_column_h - -#include "sqliterk_values.h" - -typedef struct sqliterk_column sqliterk_column; - -int sqliterkColumnAlloc(sqliterk_column **column); -int sqliterkColumnFree(sqliterk_column *column); - -sqliterk_values *sqliterkColumnGetValues(sqliterk_column *column); -void sqliterkColumnSetRowId(sqliterk_column *column, int64_t rowid); -int64_t sqliterkColumnGetRowId(sqliterk_column *column); -sqliterk_values *sqliterkColumnGetOverflowPages(sqliterk_column *column); -int sqliterkColumnClear(sqliterk_column *column); - -#endif /* sqliterk_column_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.c deleted file mode 100644 index 5881f305..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_crypto.h" -#include "SQLiteRepairKit.h" -#include "sqliterk_os.h" -#include "sqliterk_pager.h" -#ifdef WCDB_BUILTIN_SQLCIPHER -#include -#else //WCDB_BUILTIN_SQLCIPHER -#include -#endif //WCDB_BUILTIN_SQLCIPHER -#include - -// Declarations by SQLCipher. -#define CIPHER_DECRYPT 0 -#define CIPHER_ENCRYPT 1 - -#define CIPHER_READ_CTX 0 -#define CIPHER_WRITE_CTX 1 -#define CIPHER_READWRITE_CTX 2 - -/* Extensions defined in crypto_impl.c */ -typedef struct codec_ctx codec_ctx; - -/* activation and initialization */ -void sqlcipher_activate(void); -void sqlcipher_deactivate(void); - -int sqlcipher_codec_ctx_init(codec_ctx **, void *, void *, const void *, int); -void sqlcipher_codec_ctx_free(codec_ctx **); -int sqlcipher_codec_key_derive(codec_ctx *); -int sqlcipher_codec_key_copy(codec_ctx *, int); - -/* Page cipher implementation */ -int sqlcipher_page_cipher( - codec_ctx *, int, int, int, int, unsigned char *, unsigned char *); - -/* context setters & getters */ -//void sqlcipher_codec_ctx_set_error(codec_ctx *, int); - -void sqlcipher_codec_get_pass(codec_ctx *, void **, int *); -int sqlcipher_codec_ctx_set_pass(codec_ctx *, const void *, int, int); -void sqlcipher_codec_get_keyspec(codec_ctx *, void **zKey, int *nKey); - -int sqlcipher_codec_ctx_set_pagesize(codec_ctx *, int); -int sqlcipher_codec_ctx_get_pagesize(codec_ctx *); -int sqlcipher_codec_ctx_get_reservesize(codec_ctx *); - -void sqlcipher_set_default_pagesize(int page_size); -int sqlcipher_get_default_pagesize(void); - -void sqlcipher_set_default_kdf_iter(int iter); -int sqlcipher_get_default_kdf_iter(void); -int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int); -int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx); - -int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int sz); -int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void **salt); - -int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *, int); -int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *); - -const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx); - -void* sqlcipher_codec_ctx_get_data(codec_ctx *); - -//void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **); - -void sqlcipher_set_default_use_hmac(int use); -int sqlcipher_get_default_use_hmac(void); - -void sqlcipher_set_hmac_salt_mask(unsigned char mask); -unsigned char sqlcipher_get_hmac_salt_mask(void); - -int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use); -int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx, int for_ctx); - -int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag); -int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag); -int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, - unsigned int flag, - int for_ctx); - -const char *sqlcipher_codec_get_cipher_provider(codec_ctx *ctx); -//int sqlcipher_codec_ctx_migrate(codec_ctx *ctx); -int sqlcipher_codec_add_random(codec_ctx *ctx, const char *data, int random_sz); -int sqlcipher_cipher_profile(sqlite3 *db, const char *destination); -//static void sqlcipher_profile_callback(void *file, const char *sql, sqlite3_uint64 run_time); -//static int sqlcipher_codec_get_store_pass(codec_ctx *ctx); -//static void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey); -//static void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value); -int sqlcipher_codec_fips_status(codec_ctx *ctx); -const char *sqlcipher_codec_get_provider_version(codec_ctx *ctx); - - -int sqliterkCryptoSetCipher(sqliterk_pager *pager, - sqliterk_file *fd, - const sqliterk_cipher_conf *conf) -{ - codec_ctx *codec = NULL; - int rc; - - if (conf) { - // Check arguments. - if (!conf->key || conf->key_len <= 0) - return SQLITERK_MISUSE; - - // SQLite library must be initialized before calling sqlcipher_activate(), - // or it will cause a deadlock. - sqlite3_initialize(); - sqlcipher_activate(); - - // XXX: fake BTree structure passed to sqlcipher_codec_ctx_init. - // Member of such structure is assigned but never used by repair kit. - int fake_db[8]; - - // Initialize codec context. - rc = sqlcipher_codec_ctx_init(&codec, fake_db, NULL, conf->key, conf->key_len); - if (rc != SQLITE_OK) - goto bail_sqlite_errstr; - - // Read and set KDF salt. - unsigned char *salt; - unsigned char salt_buf[16]; - if (conf->kdf_salt) { - salt = (unsigned char *) conf->kdf_salt; - } else { - size_t salt_size = 16; - rc = sqliterkOSRead(fd, 0, salt_buf, &salt_size); - if (rc != SQLITERK_OK) { - sqliterkOSError(rc, "Failed to load KDF salt from file."); - goto bail; - } - salt = salt_buf; - } - sqlcipher_codec_ctx_set_kdf_salt(codec, salt, 16); - - // Set page size. - if (conf->page_size > 0) { - rc = sqlcipher_codec_ctx_set_pagesize(codec, conf->page_size); - if (rc != SQLITE_OK) - goto bail_sqlite_errstr; - } - - // Set HMAC usage. - if (conf->use_hmac >= 0) { - rc = sqlcipher_codec_ctx_set_use_hmac(codec, conf->use_hmac); - if (rc != SQLITE_OK) - goto bail_sqlite_errstr; - } - - // Set KDF Iteration. - if (conf->kdf_iter > 0) { - rc = sqlcipher_codec_ctx_set_kdf_iter(codec, conf->kdf_iter); - if (rc != SQLITE_OK) - goto bail; - } - - // Update pager page size. - int page_sz = sqlcipher_codec_ctx_get_pagesize(codec); - int reserve_sz = sqlcipher_codec_ctx_get_reservesize(codec); - - pager->pagesize = page_sz; - pager->reservedBytes = reserve_sz; - } - - if (pager->codec) { - sqlcipher_codec_ctx_free(&pager->codec); - sqlcipher_deactivate(); - } - - pager->codec = codec; - return SQLITERK_OK; - -bail_sqlite_errstr: - sqliterkOSError(SQLITERK_CANTOPEN, - "Failed to initialize cipher context: %s", - sqlite3_errstr(rc)); - rc = SQLITERK_CANTOPEN; -bail: - if (codec) - sqlcipher_codec_ctx_free(&codec); - sqlcipher_deactivate(); - return rc; -} - -void sqliterkCryptoFreeCodec(sqliterk_pager *pager) -{ - if (!pager->codec) - return; - sqlcipher_codec_ctx_free(&pager->codec); - sqlcipher_deactivate(); -} - -int sqliterkCryptoDecode(sqliterk_codec *codec, int pgno, void *data) -{ - int rc; - int offset = 0; - unsigned char *pdata = (unsigned char *) data; - - int page_sz = sqlcipher_codec_ctx_get_pagesize(codec); - unsigned char *buffer = - (unsigned char *) sqlcipher_codec_ctx_get_data(codec); - - rc = sqlcipher_codec_key_derive(codec); - if (rc != SQLITE_OK) - return rc; - - if (pgno == 1) { - offset = 16; // FILE_HEADER_SZ - memcpy(buffer, "SQLite format 3", 16); - } - rc = sqlcipher_page_cipher(codec, CIPHER_READ_CTX, pgno, CIPHER_DECRYPT, - page_sz - offset, pdata + offset, - buffer + offset); - if (rc != SQLITE_OK) - goto bail; - memcpy(pdata, buffer, page_sz); - - return SQLITERK_OK; - -bail: - sqliterkOSError(SQLITERK_DAMAGED, "Failed to decode page %d: %s", pgno, - sqlite3_errstr(rc)); - return rc; -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.h deleted file mode 100644 index 807d55fe..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_crypto.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_crypto_h -#define sqliterk_crypto_h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct sqliterk_file sqliterk_file; -typedef struct sqliterk_pager sqliterk_pager; -typedef struct codec_ctx sqliterk_codec; -typedef struct sqliterk_cipher_conf sqliterk_cipher_conf; - -int sqliterkCryptoSetCipher(sqliterk_pager *pager, - sqliterk_file *fd, - const sqliterk_cipher_conf *conf); -void sqliterkCryptoFreeCodec(sqliterk_pager *pager); -int sqliterkCryptoDecode(sqliterk_codec *codec, int pgno, void *data); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.c deleted file mode 100644 index c15c2130..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_os.h" -#include "sqliterk_util.h" -#include -#include -#include -#include -#include -#include - -struct sqliterk_file { - char *path; - int fd; - int error; // errno will be set when system error occur -}; - -int sqliterkOSReadOnlyOpen(const char *path, sqliterk_file **file) -{ - if (!path || !path[0] || !file) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_file *theFile = sqliterkOSMalloc(sizeof(sqliterk_file)); - if (!theFile) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required %zu bytes.", - sizeof(sqliterk_file)); - goto sqliterkOSReadOnlyOpen_Failed; - } - - size_t len = sizeof(char) * (strlen(path) + 1); - theFile->path = sqliterkOSMalloc(len); - if (!theFile->path) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required %zu bytes.", len); - goto sqliterkOSReadOnlyOpen_Failed; - } - strncpy(theFile->path, path, len); - - // Open the file in read-only mode, since we do not intend to modify it - theFile->fd = open(theFile->path, O_RDONLY); - if (theFile->fd < 0) { - rc = SQLITERK_CANTOPEN; - sqliterkOSError(rc, "Cannot open '%s' for reading: %s", theFile->path, - strerror(errno)); - goto sqliterkOSReadOnlyOpen_Failed; - } - *file = theFile; - return SQLITERK_OK; - -sqliterkOSReadOnlyOpen_Failed: - if (theFile) { - sqliterkOSClose(theFile); - } - *file = NULL; - return rc; -} - -int sqliterkOSClose(sqliterk_file *file) -{ - if (!file) { - return SQLITERK_MISUSE; - } - if (file->path) { - sqliterkOSFree((char *) file->path); - file->path = NULL; - } - if (file->fd >= 0) { - close(file->fd); - file->fd = -1; - } - file->error = 0; - sqliterkOSFree(file); - return SQLITERK_OK; -} - -int sqliterkOSRead(sqliterk_file *file, - off_t offset, - unsigned char *data, - size_t *size) -{ - if (!file || file->fd < 0) { - return SQLITERK_MISUSE; - } - off_t newOffset = lseek(file->fd, offset, SEEK_SET); - if (newOffset == -1) { - file->error = errno; - return SQLITERK_IOERR; - } - size_t left = *size; - size_t cnt = 0; - ssize_t got = 0; - do { - got = read(file->fd, data, left); - if (got < 0) { - if (errno == EINTR) { - got = 1; - continue; - } - file->error = errno; - return SQLITERK_IOERR; - } else if (got > 0) { - left -= got; - cnt += got; - data = data + got; - } - } while (got > 0 && left > 0); - *size = cnt; - if (left > 0) { - return SQLITERK_SHORT_READ; - } - return SQLITERK_OK; -} - -int sqliterkOSFileSize(sqliterk_file *file, size_t *filesize) -{ - if (!file || file->fd < 0) { - return SQLITERK_MISUSE; - } - struct stat statbuf; - if (fstat(file->fd, &statbuf) != 0) { - file->error = errno; - return SQLITERK_IOERR; - } - *filesize = (size_t) statbuf.st_size; - return SQLITERK_OK; -} - -const char *sqliterkOSGetFilePath(sqliterk_file *file) -{ - return file->path; -} - -void *sqliterkOSMalloc(size_t size) -{ - return calloc(size, sizeof(char)); -} - -void sqliterkOSFree(void *p) -{ - free(p); -} - -static void -sqliterkDefaultLog(sqliterk_loglevel level, int result, const char *msg) -{ - fprintf(stderr, "[%s] %s\n", sqliterkGetResultCodeDescription(result), msg); -} - -#define SQLITERK_CONFIG_MAXLOG 4096 -static sqliterk_os s_os = {sqliterkDefaultLog}; - -int sqliterkOSLog(sqliterk_loglevel loglevel, - int result, - const char *format, - ...) -{ - char buf[SQLITERK_CONFIG_MAXLOG]; - - va_list ap; - va_start(ap, format); - vsnprintf(buf, sizeof(buf), format, ap); - va_end(ap); - if (s_os.xLog) { - s_os.xLog(loglevel, result, buf); - } - return result; -} - -int sqliterkOSRegister(sqliterk_os os) -{ - s_os = os; - return SQLITERK_OK; -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.h deleted file mode 100644 index f40401d1..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_os.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_os_h -#define sqliterk_os_h - -#include "SQLiteRepairKit.h" -#include -#include - -typedef struct sqliterk_file sqliterk_file; -// sqliterk_os is the virtual layer to fit different os or platform. -// TODO -typedef struct sqliterk_os sqliterk_os; - -// memory allocation and set the allocated memory to zero-values -void *sqliterkOSMalloc(size_t size); -void sqliterkOSFree(void *p); - -int sqliterkOSLog(sqliterk_loglevel loglevel, - int result, - const char *format, - ...) -#ifdef __GNUC__ - __attribute__((format(printf, 3, 4))) -#endif - ; -int sqliterkOSRegister(sqliterk_os os); - -#define sqliterkOSDebug(result, ...) \ - sqliterkOSLog(sqliterk_loglevel_debug, result, ##__VA_ARGS__) -#define sqliterkOSWarning(result, ...) \ - sqliterkOSLog(sqliterk_loglevel_warning, result, ##__VA_ARGS__) -#define sqliterkOSError(result, ...) \ - sqliterkOSLog(sqliterk_loglevel_error, result, ##__VA_ARGS__) -#define sqliterkOSInfo(result, ...) \ - sqliterkOSLog(sqliterk_loglevel_info, result, ##__VA_ARGS__) - -int sqliterkOSReadOnlyOpen(const char *path, sqliterk_file **file); -int sqliterkOSClose(sqliterk_file *file); -int sqliterkOSRead(sqliterk_file *file, - off_t offset, - unsigned char *data, - size_t *size); -int sqliterkOSFileSize(sqliterk_file *file, size_t *filesize); -const char *sqliterkOSGetFilePath(sqliterk_file *file); - -#endif /* sqliterk_os_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_output.cpp b/Example/Pods/SQLiteRepairKit/repair/sqliterk_output.cpp deleted file mode 100644 index a262def5..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_output.cpp +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "SQLiteRepairKit.h" -#include -#include -#include -#ifdef WCDB_BUILTIN_SQLCIPHER -#include -#else //WCDB_BUILTIN_SQLCIPHER -#include -#endif //WCDB_BUILTIN_SQLCIPHER -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(__APPLE__) -#include -#include -#else -#include -#endif - -extern "C" { -#include "sqliterk_btree.h" -#include "sqliterk_os.h" -} - -class CipherContext { -public: - enum Op { - Encrypt, - Decrypt, - }; - CipherContext(Op op) -#if defined(__APPLE__) - : m_op(op), m_key(nullptr), m_keyLength(0), m_cryptor(nullptr) -#endif - { - } - - void setKey(const void *key, unsigned int keyLength) - { -#if defined(__APPLE__) - m_keyLength = keyLength; - m_key = (unsigned char *) realloc(m_key, m_keyLength); - memcpy(m_key, key, m_keyLength); -#else - RC4_set_key(&m_rc4Key, keyLength, (const unsigned char *) key); -#endif - } - - void cipher(unsigned char *data, unsigned int length) - { -#if defined(__APPLE__) - if (!m_cryptor) { - CCCryptorCreate(kCCEncrypt, kCCAlgorithmRC4, 0, m_key, m_keyLength, - nullptr, &m_cryptor); - } - - size_t cryptBytes = 0; - CCCryptorUpdate(m_cryptor, data, length, data, length, &cryptBytes); - CCCryptorFinal(m_cryptor, data, length, &cryptBytes); -#else - RC4(&m_rc4Key, length, data, data); -#endif - } - - ~CipherContext() - { -#if defined(__APPLE__) - if (m_cryptor) { - CCCryptorRelease(m_cryptor); - } - if (m_key) { - free(m_key); - } -#endif - } - -protected: -#if defined(__APPLE__) - unsigned char *m_key; - unsigned int m_keyLength; - Op m_op; - CCCryptorRef m_cryptor; -#else - RC4_KEY m_rc4Key; -#endif -}; - -struct sqliterk_master_entity { - sqliterk_type type; - std::string sql; - int root_page; - - sqliterk_master_entity() {} - - sqliterk_master_entity(sqliterk_type type_, - const char *sql_, - int root_page_) - : type(type_), sql(sql_), root_page(root_page_) - { - } -}; -typedef std::map sqliterk_master_map; -struct sqliterk_master_info : public sqliterk_master_map { -}; - -struct sqliterk_output_column_info { - char affinity; - bool not_null; - sqlite3_value *default_value = NULL; - - sqliterk_output_column_info(char aff, bool nn, sqlite3_value *dflt) : - affinity(aff), not_null(nn), default_value(dflt) {} - - sqliterk_output_column_info(sqliterk_output_column_info&& other) : - affinity(other.affinity), not_null(other.not_null), default_value(other.default_value) { - other.default_value = NULL; - } - - ~sqliterk_output_column_info() { - if (default_value) { - sqlite3_value_free(default_value); - } - } -}; - -struct sqliterk_output_ctx { - sqlite3 *db; - sqlite3_stmt *stmt; - int real_columns; - std::vector column_info; - int ipk_column; - - sqliterk_master_map tables; - sqliterk_master_map::const_iterator table_cursor; - unsigned int flags; - - unsigned int success_count; - unsigned int fail_count; - volatile unsigned cancelled; - - int (*callback)(void *user, - sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column); - void *user; -}; - -static void dummyParseTableCallback(sqliterk *rk, sqliterk_table *table) -{ -} - -static int master_onParseColumn(sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column) -{ - sqliterk_output_ctx *ctx = - (sqliterk_output_ctx *) sqliterk_get_user_info(rk); - - if (ctx->cancelled) - return SQLITERK_CANCELLED; - - // For master table, check whether we should ignore, or create table - // and prepare for insertion. - if (sqliterk_table_type(table) != sqliterk_type_master) - return SQLITERK_MISUSE; - - const char *typestr = sqliterk_column_text(column, 0); - const char *name = sqliterk_column_text(column, 1); - const char *tbl_name = sqliterk_column_text(column, 2); - int root_page = sqliterk_column_integer(column, 3); - const char *sql = sqliterk_column_text(column, 4); - sqliterk_type type; - - if (!typestr || !name || !sql || root_page <= 0) - return SQLITERK_OK; - - if (strcmp(typestr, "table") == 0) - type = sqliterk_type_table; - else if (strcmp(typestr, "index") == 0) - type = sqliterk_type_index; - else - return SQLITERK_OK; - - // TODO: deal with system tables. - if (strncmp(name, "sqlite_", 7) == 0) - return SQLITERK_OK; - - // Skip table if we are not interested. - if (!(ctx->flags & SQLITERK_OUTPUT_ALL_TABLES)) { - sqliterk_master_map::iterator it = ctx->tables.find(tbl_name); - if (it == ctx->tables.end()) - return SQLITERK_OK; - } - - // Check CREATE statement if requested. - if (ctx->flags & SQLITERK_OUTPUT_CHECK_TABLE_COLUMNS) { - sqliterk_master_map::iterator it = ctx->tables.find(name); - if (it != ctx->tables.end()) { - const sqliterk_master_entity &e = it->second; - if (e.root_page > 0 && !e.sql.empty() && - (e.type == sqliterk_type_table || e.type == sqliterk_type_index)) { - if (e.sql != sql) { - sqliterkOSWarning(SQLITERK_DAMAGED, "SQL mismatch: '%s' <-> '%s'", sql, e.sql.c_str()); - if (strlen(sql) < e.sql.size()) { - return SQLITERK_OK; - } - } - } - } - } - - ctx->tables[name] = sqliterk_master_entity(type, sql, root_page); - return SQLITERK_OK; -} - -static void fini_insert(sqliterk_output_ctx *ctx) -{ - if (ctx->stmt) { - sqlite3_finalize(ctx->stmt); - ctx->stmt = NULL; - } - - ctx->column_info.clear(); - ctx->real_columns = 0; - ctx->ipk_column = 0; -} - -static sqlite3_value *eval_value(sqlite3 *db, const char *value) -{ - if (!value || !*value) - return NULL; - - std::string sql("SELECT "); - sql += value; - sql += ';'; - sqlite3_stmt *stmt = NULL; - int rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL); - if (rc != SQLITE_OK || !stmt) { - return NULL; - } - rc = sqlite3_step(stmt); - sqlite3_value *result = NULL; - if (rc == SQLITE_ROW) { - result = sqlite3_column_value(stmt, 0); - result = sqlite3_value_dup(result); - } - sqlite3_finalize(stmt); - return result; -} - -static constexpr char SQLITE_AFF_BLOB = 'A'; -static constexpr char SQLITE_AFF_TEXT = 'B'; -static constexpr char SQLITE_AFF_NUMERIC = 'C'; -static constexpr char SQLITE_AFF_INTEGER = 'D'; -static constexpr char SQLITE_AFF_REAL = 'E'; - -static char parse_affinity(const char *type) -{ - if (!type || !*type) { - return SQLITE_AFF_BLOB; - } - - uint32_t h = 0; - char aff = SQLITE_AFF_NUMERIC; - do { - h = (h << 8) + toupper((*type++) & 0xFF); - if ((h << 8) == ('I'<<16)+('N'<<8)+'T') { - aff = SQLITE_AFF_INTEGER; - } else { - switch (h) { - case ('C'<<24)+('H'<<16)+('A'<<8)+'R':/* CHAR */ - case ('C'<<24)+('L'<<16)+('O'<<8)+'B':/* CLOB */ - case ('T'<<24)+('E'<<16)+('X'<<8)+'T':/* TEXT */ - aff = SQLITE_AFF_TEXT; - break; - case ('B'<<24)+('L'<<16)+('O'<<8)+'B':/* BLOB */ - if (aff == SQLITE_AFF_NUMERIC || aff == SQLITE_AFF_REAL) - aff = SQLITE_AFF_BLOB; - break; - case ('R'<<24)+('E'<<16)+('A'<<8)+'L':/* REAL */ - case ('F'<<24)+('L'<<16)+('O'<<8)+'A':/* FLOA */ - case ('D'<<24)+('O'<<16)+('U'<<8)+'B':/* DOUB */ - if (aff == SQLITE_AFF_NUMERIC) - aff = SQLITE_AFF_REAL; - break; - } - } - } while (*type); - return aff; -} - -static int init_insert(sqliterk_output_ctx *ctx, const std::string &table) -{ - std::string sql; - sqlite3_stmt *table_info_stmt; - - assert(ctx->stmt == NULL && ctx->column_info.empty()); - - sql.reserve(512); - sql = "PRAGMA table_info("; - sql += table; - sql += ");"; - int rc = - sqlite3_prepare_v2(ctx->db, sql.c_str(), -1, &table_info_stmt, NULL); - if (rc != SQLITE_OK) { - sqliterkOSWarning(rc, "Failed to prepare SQL: %s [SQL: %s]", - sqlite3_errmsg(ctx->db), sql.c_str()); - fini_insert(ctx); - return -1; - } - - sql = "REPLACE INTO "; - sql += table; - sql += " VALUES("; - ctx->real_columns = 0; - int ipk_column = 0; - while (sqlite3_step(table_info_stmt) == SQLITE_ROW) { - // Record the real column count defined by the SQL. - ctx->real_columns++; - - // Evaluate the default value for the rows missing some columns in B-tree. - const char *expr = (const char *) sqlite3_column_text(table_info_stmt, 4); - sqlite3_value *default_value = eval_value(ctx->db, expr); - - // Evaluate column affinity for dirty detection. - expr = (const char *) sqlite3_column_text(table_info_stmt, 2); - char aff = parse_affinity(expr); - - bool not_null = sqlite3_column_int(table_info_stmt, 3) != 0; - ctx->column_info.emplace_back(aff, not_null, default_value); - - // determine INTEGER PRIMARY KEY - if (ipk_column >= 0) { - int pk_idx = sqlite3_column_int(table_info_stmt, 5); - if (pk_idx == 1) { - const char *column_type = - (const char *) sqlite3_column_text(table_info_stmt, 2); - if (strcasecmp(column_type, "INTEGER") == 0) - ipk_column = ctx->real_columns; - } else if (pk_idx != 0) { - ipk_column = -1; - } - } - - sql += "?,"; - } - rc = sqlite3_finalize(table_info_stmt); - if (rc != SQLITE_OK || ctx->real_columns == 0) { - sqliterkOSWarning( - rc, "Failed to execute SQL: %s [SQL: PRAGMA table_info(%s);]", - sqlite3_errmsg(ctx->db), table.c_str()); - fini_insert(ctx); - return -1; - } - - sql[sql.length() - 1] = ')'; - sql += ';'; - - sqlite3_stmt *stmt; - rc = sqlite3_prepare_v2(ctx->db, sql.c_str(), -1, &stmt, NULL); - if (rc != SQLITE_OK) { - sqliterkOSWarning(rc, "Failed to prepare SQL: %s [SQL: %s]", - sqlite3_errmsg(ctx->db), sql.c_str()); - fini_insert(ctx); - return -1; - } - ctx->stmt = stmt; - ctx->ipk_column = (ipk_column > 0) ? ipk_column : 0; - - return ctx->real_columns; -} - -static void table_onBeginParseTable(sqliterk *rk, sqliterk_table *table) -{ - sqliterk_output_ctx *ctx = - (sqliterk_output_ctx *) sqliterk_get_user_info(rk); - - sqliterkBtreeSetMeta((sqliterk_btree *) table, - ctx->table_cursor->first.c_str(), - sqliterk_btree_type_table); -} - -static int table_onParseColumn(sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column) -{ - sqliterk_output_ctx *ctx = - (sqliterk_output_ctx *) sqliterk_get_user_info(rk); - - if (ctx->cancelled) - return SQLITERK_CANCELLED; - - int rc; - if (ctx->callback) { - rc = ctx->callback(ctx->user, rk, table, column); - if (rc != SQLITERK_OK) { - if (rc == SQLITERK_IGNORE) - rc = SQLITERK_OK; - return rc; - } - } - - int columns = sqliterk_column_count(column); - sqlite3_stmt *stmt = ctx->stmt; - - if (!stmt) { - // Invalid table_cursor means failed statement compilation. - if (ctx->table_cursor == ctx->tables.end()) { - ctx->fail_count++; - return SQLITERK_OK; - } - - rc = init_insert(ctx, ctx->table_cursor->first); - if (rc <= 0) { - ctx->table_cursor = ctx->tables.end(); - ctx->fail_count++; - return SQLITERK_OK; - } - - // Begin transaction. - char *errmsg; - rc = sqlite3_exec(ctx->db, "BEGIN;", NULL, NULL, &errmsg); - if (errmsg) { - sqliterkOSWarning(rc, "Failed to begin transaction: %s", errmsg); - sqlite3_free(errmsg); - } - - stmt = ctx->stmt; - } - - int i; - - // Check column count: if row has more columns in B-tree than in SQL statement, it's probably - // come from wrong table and should consider corrupted. - if (columns > ctx->real_columns || columns > ctx->column_info.size()) { - sqliterkOSWarning(SQLITERK_DAMAGED, "Column count mismatch: %d vs %d", columns, ctx->real_columns); - ctx->fail_count++; - return SQLITERK_OK; - } - - // Bind values provided by the repair kit. - sqlite3_clear_bindings(stmt); - for (i = 0; i < columns; i++) { - sqliterk_value_type type = sqliterk_column_type(column, i); - switch (type) { - case sqliterk_value_type_binary: - sqlite3_bind_blob(stmt, i + 1, - sqliterk_column_binary(column, i), - sqliterk_column_bytes(column, i), NULL); - break; - case sqliterk_value_type_integer: - // INTEGER value should not be stored in columns with TEXT affinity. - if (ctx->column_info[i].affinity == SQLITE_AFF_TEXT) { - sqliterkOSWarning(SQLITERK_DAMAGED, "INTEGER value detected in column with TEXT affinity."); - ctx->fail_count++; - return SQLITERK_OK; - } - - sqlite3_bind_int64(stmt, i + 1, - sqliterk_column_integer64(column, i)); - break; - case sqliterk_value_type_null: - // If NOT NULL is defined in this column, the recovered row is considered corrupted. - if (ctx->column_info[i].not_null) { - sqliterkOSWarning(SQLITERK_DAMAGED, "NULL value detected in NOT NULL column."); - ctx->fail_count++; - return SQLITERK_OK; - } - - // If it's INTEGER PRIMARY KEY column, bind rowid instead. - if (ctx->ipk_column == i + 1) - sqlite3_bind_int64(stmt, i + 1, - sqliterk_column_rowid(column)); - else - sqlite3_bind_null(stmt, i + 1); - break; - case sqliterk_value_type_number: - // REAL value should not be stored in columns with TEXT affinity. - if (ctx->column_info[i].affinity == SQLITE_AFF_TEXT) { - sqliterkOSWarning(SQLITERK_DAMAGED, "REAL value detected in column with TEXT affinity."); - ctx->fail_count++; - return SQLITERK_OK; - } - - sqlite3_bind_double(stmt, i + 1, - sqliterk_column_number(column, i)); - break; - case sqliterk_value_type_text: - sqlite3_bind_text(stmt, i + 1, sqliterk_column_text(column, i), - sqliterk_column_bytes(column, i), NULL); - break; - } - } - - // Use defaults for remaining values. - for (; i < ctx->real_columns; i++) { - sqlite3_value *v = ctx->column_info[i].default_value; - if (v) { - sqlite3_bind_value(stmt, i, v); - } - } - - while (sqlite3_step(stmt) == SQLITE_ROW) { - } - rc = sqlite3_reset(stmt); - if (rc != SQLITE_OK) { - sqliterkOSWarning(rc, "Failed to execute SQL: %s [SQL: %s]", - sqlite3_errmsg(ctx->db), sqlite3_sql(stmt)); - ctx->fail_count++; - return SQLITERK_OK; - } - - ctx->success_count++; - if (ctx->success_count % 256 == 0) { - char *errmsg; - rc = sqlite3_exec(ctx->db, "COMMIT; BEGIN;", NULL, NULL, &errmsg); - if (errmsg) { - sqliterkOSWarning(rc, "Failed to commit transaction: %s", errmsg); - sqlite3_free(errmsg); - } - } - - return SQLITERK_OK; -} - -int sqliterk_output(sqliterk *rk, - sqlite3 *db, - sqliterk_master_info *master_, - unsigned int flags) -{ - return sqliterk_output_cb(rk, db, master_, flags, NULL, NULL); -} - -int sqliterk_output_cb(sqliterk *rk, - sqlite3 *db, - sqliterk_master_info *master_, - unsigned int flags, - int (*callback)(void *user, - sqliterk *rk, - sqliterk_table *table, - sqliterk_column *column), - void *user) -{ - if (!rk || !db) - return SQLITERK_MISUSE; - - sqliterk_master_map *master = static_cast(master_); - sqliterk_output_ctx ctx; - ctx.db = db; - ctx.stmt = NULL; - ctx.flags = flags; - ctx.success_count = 0; - ctx.fail_count = 0; - ctx.ipk_column = 0; - ctx.callback = callback; - ctx.user = user; - ctx.cancelled = 0; - - if (!master) - ctx.flags |= SQLITERK_OUTPUT_ALL_TABLES; - else - ctx.tables = *master; - - sqliterk_set_user_info(rk, &ctx); - sqliterk_notify notify; - notify.onBeginParseTable = dummyParseTableCallback; - notify.onEndParseTable = dummyParseTableCallback; - notify.onParseColumn = master_onParseColumn; - notify.didParsePage = NULL; - sqliterk_register_notify(rk, notify); - sqliterk_set_recursive(rk, 0); - - const char *db_file = sqlite3_db_filename(db, "main"); - sqliterkOSInfo(SQLITERK_OK, "Output recovered data to '%s', flags 0x%04x", - db_file ? db_file : "unknown", flags); - - // Parse sqlite_master for table info. - sqliterkOSDebug(SQLITERK_OK, "Begin parsing sqlite_master..."); - int rc = sqliterk_parse_page(rk, 1); - if (rc == SQLITERK_CANCELLED) { - goto cancelled; - } else if (rc != SQLITERK_OK) - sqliterkOSWarning(rc, "Failed to parse sqlite_master."); - else - sqliterkOSInfo(rc, "Parsed sqlite_master. [table/index: %zu]", - ctx.tables.size()); - - // Parse all tables. - notify.onBeginParseTable = table_onBeginParseTable; - notify.onParseColumn = table_onParseColumn; - sqliterk_register_notify(rk, notify); - - for (sqliterk_master_map::iterator it = ctx.tables.begin(); - it != ctx.tables.end(); ++it) { - if (ctx.cancelled) - goto cancelled; - - if (it->second.type != sqliterk_type_table) - continue; - - // Run CREATE TABLE statements if necessary. - if (!(ctx.flags & SQLITERK_OUTPUT_NO_CREATE_TABLES) && - !it->second.sql.empty()) { - sqliterkOSInfo(SQLITERK_OK, ">>> %s", it->second.sql.c_str()); - char *errmsg = NULL; - const char *sql = it->second.sql.c_str(); - rc = sqlite3_exec(ctx.db, sql, NULL, NULL, &errmsg); - if (errmsg) { - sqliterkOSWarning(rc, "EXEC FAILED: %s [SQL: %s]", errmsg, sql); - ctx.fail_count++; - sqlite3_free(errmsg); - } else - ctx.success_count++; - } - - if (it->second.root_page != 0) { - const char *name = it->first.c_str(); - int root_page = it->second.root_page; - sqliterkOSInfo(SQLITERK_OK, "[%s] -> pgno: %d", name, root_page); - ctx.table_cursor = it; - rc = sqliterk_parse_page(rk, root_page); - if (ctx.stmt) { - const char *sql = - (rc == SQLITERK_CANCELLED) ? "ROLLBACK;" : "COMMIT;"; - - // Commit transaction and free statement. - char *errmsg; - int rc2 = sqlite3_exec(ctx.db, sql, NULL, NULL, &errmsg); - if (errmsg) { - sqliterkOSWarning(rc2, "Failed to commit transaction: %s", - errmsg); - sqlite3_free(errmsg); - } - - fini_insert(&ctx); - } - if (rc == SQLITERK_CANCELLED) { - goto cancelled; - } else if (rc != SQLITERK_OK) { - sqliterkOSWarning(rc, - "Failed to parse B-tree with root page %d.", - it->second.root_page); - } - } - } - - // Iterate through indices, create them if necessary. - if (!(ctx.flags & SQLITERK_OUTPUT_NO_CREATE_TABLES)) { - for (sqliterk_master_map::iterator it = ctx.tables.begin(); - it != ctx.tables.end(); ++it) { - if (ctx.cancelled) - goto cancelled; - - if (it->second.type != sqliterk_type_index) - continue; - - const char *sql = it->second.sql.c_str(); - sqliterkOSDebug(SQLITERK_OK, ">>> %s", sql); - char *errmsg = NULL; - rc = sqlite3_exec(ctx.db, sql, NULL, NULL, &errmsg); - if (errmsg) { - sqliterkOSWarning(rc, "EXEC FAILED: %s [SQL: %s]", errmsg, sql); - ctx.fail_count++; - sqlite3_free(errmsg); - } else - ctx.success_count++; - } - } - - // Return OK only if we had successfully output at least one row. - if (ctx.success_count == 0) { - if (ctx.tables.empty()) - sqliterkOSError(SQLITERK_DAMAGED, - "No valid sqlite_master info available, " - "sqlite_master is corrupted."); - else - sqliterkOSError(SQLITERK_DAMAGED, - "No rows can be successfully output. [failed: %u]", - ctx.fail_count); - return SQLITERK_DAMAGED; - } else { - sqliterkOSInfo(SQLITERK_OK, - "Recovery output finished. [succeeded: %u, failed: %u]", - ctx.success_count, ctx.fail_count); - return SQLITERK_OK; - } - - cancelled: - sqliterkOSInfo(SQLITERK_CANCELLED, - "Recovery cancelled. [succeeded: %u, failed: %u]", - ctx.success_count, ctx.fail_count); - return SQLITERK_CANCELLED; -} - -void sqliterk_cancel(sqliterk *rk) -{ - sqliterk_output_ctx *ctx = - (sqliterk_output_ctx *) sqliterk_get_user_info(rk); - if (ctx) { - ctx->cancelled = 1; - } -} - -int sqliterk_make_master(const char **tables, - int num_tables, - sqliterk_master_info **out_master) -{ - if (!tables || !num_tables) { - *out_master = NULL; - return SQLITERK_OK; - } - - sqliterk_master_map *master = new sqliterk_master_map(); - for (int i = 0; i < num_tables; i++) - (*master)[tables[i]] = - sqliterk_master_entity(sqliterk_type_unknown, "", 0); - - *out_master = static_cast(master); - return SQLITERK_OK; -} - -#define SQLITERK_SM_TYPE_TABLE 0x01 -#define SQLITERK_SM_TYPE_INDEX 0x02 - -#define SQLITERK_SM_MAGIC "\0dBmSt" -#define SQLITERK_SM_VERSION 1 - -#pragma pack(push, 1) -struct master_file_header { - char magic[6]; - uint16_t version; - uint32_t entities; - unsigned char kdf_salt[16]; -}; - -struct master_file_entity { - uint32_t root_page; - uint8_t type; - uint8_t name_len; - uint8_t tbl_name_len; - uint8_t reserved; - uint16_t sql_len; - - unsigned char data[0]; -}; -#pragma pack(pop) - -int sqliterk_save_master(sqlite3 *db, - const char *path, - const void *key, - int key_len) -{ - FILE *fp = NULL; - int rc = SQLITERK_OK; - sqlite3_stmt *stmt = NULL; - z_stream zstrm = {0}; - CipherContext cipherContext(CipherContext::Encrypt); - unsigned char in_buf[512 + 8]; - unsigned char out_buf[2048]; - uint32_t entities = 0; - master_file_header header; - - // Prepare deflate stream. - rc = deflateInit(&zstrm, Z_DEFAULT_COMPRESSION); - if (rc != Z_OK) - goto bail_zlib; - zstrm.data_type = Z_TEXT; - - // Open output file. - fp = fopen(path, "wb"); - if (!fp) - goto bail_errno; - - // Prepare cipher key. - if (key && key_len) { - cipherContext.setKey(key, key_len); - } else { - key = NULL; - } - - // Prepare SQL statement. - rc = - sqlite3_prepare_v2(db, "SELECT * FROM sqlite_master;", -1, &stmt, NULL); - if (rc != SQLITE_OK) - goto bail_sqlite; - - // Write dummy header. - memset(&header, 0, sizeof(header)); - if (fwrite(&header, sizeof(header), 1, fp) != 1) - goto bail_errno; - - // Read all rows. - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - const char *typestr = (const char *) sqlite3_column_text(stmt, 0); - int name_len = sqlite3_column_bytes(stmt, 1); - const char *name = (const char *) sqlite3_column_text(stmt, 1); - int tbl_name_len = sqlite3_column_bytes(stmt, 2); - const char *tbl_name = (const char *) sqlite3_column_text(stmt, 2); - int root_page = sqlite3_column_int(stmt, 3); - int sql_len = sqlite3_column_bytes(stmt, 4); - const char *sql = (const char *) sqlite3_column_text(stmt, 4); - - // Skip invalid rows. - if (!typestr || !name || !tbl_name || !sql) - continue; - - // Skip system tables and indices. - if (strncmp(name, "sqlite_", 7) == 0) - continue; - - unsigned char type; - if (strcmp(typestr, "table") == 0) - type = SQLITERK_SM_TYPE_TABLE; - else if (strcmp(typestr, "index") == 0) - type = SQLITERK_SM_TYPE_INDEX; - else - continue; - - if (name_len > 255 || tbl_name_len > 255 || sql_len > 65535) { - sqliterkOSError(SQLITERK_IOERR, - "Table/index has name longer than 255: %s, %s", - name, tbl_name); - goto bail; - } - - // Write to zip-stream buffer. - master_file_entity *entity = (master_file_entity *) in_buf; - entity->root_page = root_page; - entity->type = type; - entity->name_len = (unsigned char) name_len; - entity->tbl_name_len = (unsigned char) tbl_name_len; - entity->reserved = 0; - entity->sql_len = (unsigned short) sql_len; - unsigned char *p_data = entity->data; - memcpy(p_data, name, name_len + 1); - p_data += name_len + 1; - memcpy(p_data, tbl_name, tbl_name_len + 1); - p_data += tbl_name_len + 1; - - zstrm.next_in = in_buf; - zstrm.avail_in = (uInt)(p_data - in_buf); - - do { - zstrm.next_out = out_buf; - zstrm.avail_out = sizeof(out_buf); - rc = deflate(&zstrm, Z_NO_FLUSH); - if (rc == Z_STREAM_ERROR) - goto bail_zlib; - - unsigned have = sizeof(out_buf) - zstrm.avail_out; - if (key) { - cipherContext.cipher(out_buf, have); - } - if (fwrite(out_buf, 1, have, fp) != have) { - sqliterkOSError(SQLITERK_IOERR, - "Cannot write to backup file: %s", - strerror(errno)); - goto bail; - } - } while (zstrm.avail_out == 0); - - zstrm.next_in = (unsigned char *) sql; - zstrm.avail_in = sql_len + 1; - - do { - zstrm.next_out = out_buf; - zstrm.avail_out = sizeof(out_buf); - rc = deflate(&zstrm, Z_NO_FLUSH); - if (rc == Z_STREAM_ERROR) - goto bail_zlib; - - unsigned have = sizeof(out_buf) - zstrm.avail_out; - if (key) { - cipherContext.cipher(out_buf, have); - } - if (fwrite(out_buf, 1, have, fp) != have) { - sqliterkOSError(SQLITERK_IOERR, - "Cannot write to backup file: %s", - strerror(errno)); - goto bail; - } - } while (zstrm.avail_out == 0); - - entities++; - } // sqlite3_step - rc = sqlite3_finalize(stmt); - stmt = NULL; - if (rc != SQLITE_OK) - goto bail_sqlite; - - // Flush Z-stream. - zstrm.avail_in = 0; - do { - zstrm.next_out = out_buf; - zstrm.avail_out = sizeof(out_buf); - rc = deflate(&zstrm, Z_FINISH); - if (rc == Z_STREAM_ERROR) - goto bail_zlib; - - unsigned have = sizeof(out_buf) - zstrm.avail_out; - if (key) { - cipherContext.cipher(out_buf, have); - } - if (fwrite(out_buf, 1, have, fp) != have) { - sqliterkOSError(SQLITERK_IOERR, "Cannot write to backup file: %s", - strerror(errno)); - goto bail; - } - } while (zstrm.avail_out == 0); - deflateEnd(&zstrm); - - // Read KDF salt from file header. - sqlite3_file *db_file; - rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &db_file); - if (rc != SQLITE_OK) - goto bail_sqlite; - - rc = db_file->pMethods->xRead(db_file, header.kdf_salt, - sizeof(header.kdf_salt), 0); - if (rc != SQLITE_OK) - goto bail_sqlite; - - // Write real header. - memcpy(header.magic, SQLITERK_SM_MAGIC, sizeof(header.magic)); - header.version = SQLITERK_SM_VERSION; - header.entities = entities; - fseek(fp, 0, SEEK_SET); - fwrite(&header, sizeof(header), 1, fp); - fclose(fp); - - sqliterkOSInfo(SQLITERK_OK, "Saved master info with %u entries.", entities); - return SQLITERK_OK; - - bail_zlib: - sqliterkOSError(SQLITERK_CANTOPEN, "Failed to backup master table: %s", - zstrm.msg); - goto bail; - bail_errno: - sqliterkOSError(rc, "Failed to backup master table: %s", strerror(errno)); - goto bail; - bail_sqlite: - sqliterkOSError(rc, "Failed to backup master table: %s", - sqlite3_errmsg(db)); - - bail: - if (fp) - fclose(fp); - if (stmt) - sqlite3_finalize(stmt); - deflateEnd(&zstrm); - return rc; -} - -static const size_t IN_BUF_SIZE = 4096; -static int inflate_read(FILE *fp, - z_streamp strm, - void *buf, - unsigned size, - CipherContext *cipherContext) -{ - int ret; - if (size == 0) - return SQLITERK_OK; - - strm->next_out = (unsigned char *) buf; - strm->avail_out = size; - - do { - if (strm->avail_in == 0 && !feof(fp)) { - unsigned char *in_buf = strm->next_in - strm->total_in; - strm->total_in = 0; - - ret = (int) fread(in_buf, 1, IN_BUF_SIZE, fp); - if (ret == 0 && ferror(fp)) - return SQLITERK_IOERR; - if (ret > 0) { - if (cipherContext) { - cipherContext->cipher(in_buf, ret); - } - strm->next_in = in_buf; - strm->avail_in = ret; - } - } - - ret = inflate(strm, Z_NO_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - return SQLITERK_DAMAGED; - - } while (strm->avail_out > 0 && ret != Z_STREAM_END); - - return strm->avail_out ? SQLITERK_DAMAGED : SQLITERK_OK; -} - -static int pstrcmp(const void *p1, const void *p2) -{ - return strcmp(*(char *const *) p1, *(char *const *) p2); -} - -int sqliterk_load_master(const char *path, - const void *key, - int key_len, - const char **tables, - int num_tables, - sqliterk_master_info **out_master, - unsigned char *out_kdf_salt) -{ - FILE *fp = NULL; - z_stream zstrm = {0}; - CipherContext cipherContext(CipherContext::Decrypt); - int rc; - unsigned char in_buf[IN_BUF_SIZE]; - const char **filter = NULL; - sqliterk_master_map *master = NULL; - uint32_t entities; - - // Allocate output buffer. - char *str_buf = (char *) malloc(65536 + 512); - if (!str_buf) - goto bail_errno; - - // Sort table filter for later binary searching. - if (tables && num_tables) { - sqliterk_make_master(tables, num_tables, - (sqliterk_master_info **) &master); - - size_t filter_size = num_tables * sizeof(const char *); - filter = (const char **) malloc(filter_size); - if (!filter) - goto bail_errno; - - memcpy(filter, tables, filter_size); - qsort(filter, num_tables, sizeof(const char *), pstrcmp); - } - if (!master) - master = new sqliterk_master_map(); - - fp = fopen(path, "rb"); - if (!fp) - goto bail_errno; - - // Read header. - master_file_header header; - if (fread(&header, sizeof(header), 1, fp) != 1) - goto bail_errno; - if (memcmp(header.magic, SQLITERK_SM_MAGIC, sizeof(header.magic)) != 0 || - header.version != SQLITERK_SM_VERSION) { - sqliterkOSError(SQLITERK_DAMAGED, "Invalid format: %s", path); - goto bail; - } - - // Initialize zlib and RC4. - rc = inflateInit(&zstrm); - if (rc != Z_OK) - goto bail_zlib; - - if (key && key_len) { - cipherContext.setKey(key, key_len); - } else { - key = NULL; - } - - // Read all entities. - entities = header.entities; - zstrm.next_in = in_buf; - zstrm.avail_in = 0; - while (entities--) { - // Read entity header. - master_file_entity entity; - rc = inflate_read(fp, &zstrm, &entity, sizeof(entity), - key ? &cipherContext : NULL); - if (rc == SQLITERK_IOERR) - goto bail_errno; - else if (rc == SQLITERK_DAMAGED) - goto bail_zlib; - - // Read names and SQL. - rc = inflate_read(fp, &zstrm, str_buf, - entity.name_len + entity.tbl_name_len + - entity.sql_len + 3, - key ? &cipherContext : NULL); - if (rc == SQLITERK_IOERR) - goto bail_errno; - else if (rc == SQLITERK_DAMAGED) - goto bail_zlib; - - const char *name = str_buf; - const char *tbl_name = name + entity.name_len + 1; - const char *sql = tbl_name + entity.tbl_name_len + 1; - if (name[entity.name_len] != '\0' || - tbl_name[entity.tbl_name_len] != '\0' || - sql[entity.sql_len] != '\0') { - sqliterkOSError(SQLITERK_DAMAGED, - "Invalid string. File corrupted."); - goto bail; - } - - // Filter tables. - if (!filter || bsearch(&tbl_name, filter, num_tables, - sizeof(const char *), pstrcmp)) { - sqliterk_master_entity e(sqliterk_type_unknown, sql, - entity.root_page); - if (entity.type == SQLITERK_SM_TYPE_TABLE) - e.type = sqliterk_type_table; - else if (entity.type == SQLITERK_SM_TYPE_INDEX) - e.type = sqliterk_type_index; - - (*master)[name] = e; - } - } - - inflateEnd(&zstrm); - free(str_buf); - free(filter); - fclose(fp); - - if (out_kdf_salt) - memcpy(out_kdf_salt, header.kdf_salt, sizeof(header.kdf_salt)); - *out_master = static_cast(master); - sqliterkOSInfo(SQLITERK_OK, "Loaded master info with %zu valid entries.", - master->size()); - return SQLITERK_OK; - - bail_errno: - sqliterkOSError(SQLITERK_IOERR, "Cannot load master table: %s", - strerror(errno)); - goto bail; - bail_zlib: - sqliterkOSError(SQLITERK_DAMAGED, "Cannot load master table: %s", - zstrm.msg); - bail: - if (master) - delete master; - free(str_buf); - free(filter); - inflateEnd(&zstrm); - if (fp) - fclose(fp); - return SQLITERK_DAMAGED; -} - -void sqliterk_free_master(sqliterk_master_info *master) -{ - if (master) - delete static_cast(master); -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.c deleted file mode 100644 index 4dd21b15..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_pager.h" -#include "SQLiteRepairKit.h" -#include "sqliterk_crypto.h" -#include "sqliterk_os.h" -#include "sqliterk_util.h" -#include -#include - -static int sqliterkPagerParseHeader(sqliterk_pager *pager, int forcePageSize); -static int sqliterkPageAcquireOne(sqliterk_pager *pager, - int pageno, - sqliterk_page **page, - sqliterk_page_type type); - -struct sqliterk_page { - int pageno; - unsigned char *data; // page data - sqliterk_page_type type; -}; - -int sqliterkPagerOpen(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk_pager **pager) -{ - // Workaround page size cannot be specified for plain-text - // databases. For that case, pass non-null cipher_conf with - // null key and non-zero page size. - int forcePageSize = 0; - if (cipher && !cipher->key) { - forcePageSize = cipher->page_size; - cipher = NULL; - } - - if (!pager) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_pager *thePager = sqliterkOSMalloc(sizeof(sqliterk_pager)); - if (!thePager) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required %zu bytes.", - sizeof(sqliterk_pager)); - goto sqliterkPagerOpen_Failed; - } - - rc = sqliterkOSReadOnlyOpen(path, &thePager->file); - if (rc != SQLITERK_OK) { - goto sqliterkPagerOpen_Failed; - } - - if (cipher) { - // Try KDF salt in SQLite file first. - sqliterk_cipher_conf c; - memcpy(&c, cipher, sizeof(c)); - c.kdf_salt = NULL; - - rc = sqliterkCryptoSetCipher(thePager, thePager->file, &c); - if (rc != SQLITERK_OK) - goto sqliterkPagerOpen_Failed; - - // Try parsing header. - sqliterkPagerParseHeader(thePager, 0); - - if (thePager->integrity & SQLITERK_INTEGRITY_HEADER) { - // If header is parsed successfully, original KDF salt is also correct. - thePager->integrity |= SQLITERK_INTEGRITY_KDF_SALT; - } else if (cipher->kdf_salt) { - // If anything goes wrong, use KDF salt specified in cipher config. - sqliterkOSWarning(SQLITERK_DAMAGED, "Header cannot be decoded " - "correctly. Trying to apply " - "recovery data."); - rc = sqliterkCryptoSetCipher(thePager, thePager->file, cipher); - if (rc != SQLITERK_OK) - goto sqliterkPagerOpen_Failed; - - rc = sqliterkPagerParseHeader(thePager, 0); - if (rc != SQLITERK_OK) - goto sqliterkPagerOpen_Failed; - } - } else { - rc = sqliterkPagerParseHeader(thePager, forcePageSize); - if (rc != SQLITERK_OK) - goto sqliterkPagerOpen_Failed; - - // For plain-text databases, just mark KDF salt correct. - if (thePager->integrity & SQLITERK_INTEGRITY_HEADER) - thePager->integrity |= SQLITERK_INTEGRITY_KDF_SALT; - } - if (!(thePager->integrity & SQLITERK_INTEGRITY_HEADER)) - sqliterkOSWarning(SQLITERK_DAMAGED, "Header corrupted."); - else - sqliterkOSInfo(SQLITERK_OK, "Header checksum OK."); - - int pageCount = thePager->pagecount; - size_t len = sizeof(sqliterk_status) * (pageCount + 1); - thePager->pagesStatus = sqliterkOSMalloc(len); - if (!thePager->pagesStatus) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required %zu bytes.", len); - goto sqliterkPagerOpen_Failed; - } - - *pager = thePager; - - return SQLITERK_OK; - -sqliterkPagerOpen_Failed: - if (thePager) { - sqliterkPagerClose(thePager); - } - *pager = NULL; - return rc; -} - -// Get the meta from header and set it into pager. -// For further information, see https://www.sqlite.org/fileformat2.html -static int sqliterkPagerParseHeader(sqliterk_pager *pager, int forcePageSize) -{ - // For encrypted databases, assume default page size, decode the first - // page, and we have the plain-text header. - - if (!pager) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - - // Overwrite pager page size if forcePageSize is specified. - if (forcePageSize) { - pager->pagesize = forcePageSize; - } - - size_t size = pager->codec ? pager->pagesize : 100; - - // Read data - unsigned char *buffer = sqliterkOSMalloc(size); - if (!buffer) { - rc = SQLITERK_NOMEM; - sqliterkOSError(rc, "Not enough memory, required %zu bytes.", size); - goto sqliterkPagerParseHeader_End; - } - - rc = sqliterkOSRead(pager->file, 0, buffer, &size); - if (rc != SQLITERK_OK) { - if (rc == SQLITERK_SHORT_READ) - sqliterkOSError(rc, "File truncated."); - else - sqliterkOSError(rc, "Cannot read file '%s': %s", - sqliterkOSGetFilePath(pager->file), - strerror(errno)); - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - goto sqliterkPagerParseHeader_End; - } - - pager->integrity |= SQLITERK_INTEGRITY_HEADER; - - if (pager->codec) { - rc = sqliterkCryptoDecode(pager->codec, 1, buffer); - if (rc != SQLITERK_OK) { - sqliterkOSWarning(SQLITERK_DAMAGED, - "Failed to decode page 1, header corrupted."); - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } - } - - if (pager->integrity & SQLITERK_INTEGRITY_HEADER) { - if (memcmp(buffer, "SQLite format 3\000", 16) == 0) { - //parse pagesize - int pagesize; - sqliterkParseInt(buffer, 16, 2, &pagesize); - if (pager->codec || forcePageSize) { - // Page size is predefined, check whether it matches the header. - if (pagesize != pager->pagesize) { - sqliterkOSWarning( - SQLITERK_DAMAGED, - "Invalid page size: %d expected, %d returned.", - pager->pagesize, pagesize); - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } - } else if (((pagesize - 1) & pagesize) != 0 || pagesize < 512) { - // Page size is not predefined and value in the header is invalid, - // use the default page size. - sqliterkOSWarning(SQLITERK_DAMAGED, - "Page size field is corrupted. Default page " - "size %d is used", - SQLITRK_CONFIG_DEFAULT_PAGESIZE); - pager->pagesize = SQLITRK_CONFIG_DEFAULT_PAGESIZE; - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } else { - // Page size is not predefined and value in the header is valid, - // use the value in header. - pager->pagesize = pagesize; - } - - // parse free page count - sqliterkParseInt(buffer, 36, 4, &pager->freepagecount); - - // parse reserved bytes - int reservedBytes; - sqliterkParseInt(buffer, 20, 1, &reservedBytes); - if (pager->codec) { - if (reservedBytes != pager->reservedBytes) { - sqliterkOSWarning(SQLITERK_DAMAGED, - "Reserved bytes field doesn't match. %d " - "expected, %d returned.", - pager->reservedBytes, reservedBytes); - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } - } else if (reservedBytes < 0 || reservedBytes > 255) { - sqliterkOSWarning( - SQLITERK_DAMAGED, - "The [reserved bytes] field is corrupted. 0 is used"); - pager->reservedBytes = 0; - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } else - pager->reservedBytes = reservedBytes; - } else { - // Header is corrupted. Defaults the config - sqliterkOSWarning(SQLITERK_DAMAGED, - "SQLite format magic corrupted."); - if (!pager->codec) { - pager->pagesize = SQLITRK_CONFIG_DEFAULT_PAGESIZE; - pager->reservedBytes = 0; - } - pager->freepagecount = 0; - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } - } - - // Assign page count - size_t filesize; - rc = sqliterkOSFileSize(pager->file, &filesize); - if (rc != SQLITERK_OK) { - sqliterkOSError(rc, "Failed to get size of file '%s': %s", - sqliterkOSGetFilePath(pager->file), strerror(errno)); - goto sqliterkPagerParseHeader_End; - } - - pager->pagecount = - (int) ((filesize + pager->pagesize - 1) / pager->pagesize); - if (pager->pagecount < 1) { - rc = SQLITERK_DAMAGED; - sqliterkOSError(rc, "File truncated."); - goto sqliterkPagerParseHeader_End; - } - - // Check free page - if (pager->freepagecount < 0 || pager->freepagecount > pager->pagecount) { - sqliterkOSWarning( - SQLITERK_DAMAGED, - "The [free page count] field is corrupted. 0 is used"); - pager->freepagecount = 0; - pager->integrity &= ~SQLITERK_INTEGRITY_HEADER; - } - - // Assign usableSize - pager->usableSize = pager->pagesize - pager->reservedBytes; - -sqliterkPagerParseHeader_End: - if (buffer) { - sqliterkOSFree(buffer); - } - return rc; -} - -int sqliterkPagerClose(sqliterk_pager *pager) -{ - if (!pager) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - if (pager->file) { - rc = sqliterkOSClose(pager->file); - pager->file = NULL; - } - if (pager->pagesStatus) { - sqliterkOSFree(pager->pagesStatus); - pager->pagesStatus = NULL; - } - pager->pagesize = 0; - pager->pagecount = 0; - - sqliterkCryptoFreeCodec(pager); - - sqliterkOSFree(pager); - return rc; -} - -int sqliterkPagerGetPageCount(sqliterk_pager *pager) -{ - if (!pager) { - return 0; - } - return pager->pagecount; -} - -int sqliterkPagerIsPagenoValid(sqliterk_pager *pager, int pageno) -{ - if (!pager || pageno < 1 || pageno > pager->pagecount) { - return SQLITERK_MISUSE; - } - return SQLITERK_OK; -} - -// Get the page type from file at page [pageno] -int sqliterkPageAcquireType(sqliterk_pager *pager, - int pageno, - sqliterk_page_type *type) -{ - // TODO: for encrypted databases, decode the whole page. - // Use sqliterkPageAcquire instead. - - if (!pager || sqliterkPagerIsPagenoValid(pager, pageno) != SQLITERK_OK || - !type) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - unsigned char typedata; - size_t typesize = 1; - rc = sqliterkOSRead(pager->file, - sqliterkPagenoHeaderOffset(pageno) + - (pageno - 1) * pager->pagesize, - &typedata, &typesize); - if (rc != SQLITERK_OK) { - goto sqliterkPageAcquireType_Failed; - } - - int theType; - sqliterkParseInt(&typedata, 0, 1, &theType); - switch (theType) { - case sqliterk_page_type_interior_index: - case sqliterk_page_type_interior_table: - case sqliterk_page_type_leaf_index: - case sqliterk_page_type_leaf_table: - *type = theType; - break; - default: - *type = sqliterk_page_type_unknown; - break; - } - return SQLITERK_OK; - -sqliterkPageAcquireType_Failed: - *type = sqliterk_page_type_unknown; - return rc; -} - -// Get whole page data from file at page [pageno] and setup the [page]. -int sqliterkPageAcquire(sqliterk_pager *pager, int pageno, sqliterk_page **page) -{ - return sqliterkPageAcquireOne(pager, pageno, page, - sqliterk_page_type_unknown); -} - -int sqliterkPageAcquireOverflow(sqliterk_pager *pager, - int pageno, - sqliterk_page **page) -{ - return sqliterkPageAcquireOne(pager, pageno, page, - sqliterk_page_type_overflow); -} - -static int sqliterkPageAcquireOne(sqliterk_pager *pager, - int pageno, - sqliterk_page **page, - sqliterk_page_type type) -{ - if (!pager || !page || - sqliterkPagerIsPagenoValid(pager, pageno) != SQLITERK_OK) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_page *thePage = sqliterkOSMalloc(sizeof(sqliterk_page)); - if (!thePage) { - rc = SQLITERK_NOMEM; - goto sqliterkPageAcquire_Failed; - } - - thePage->pageno = pageno; - - thePage->data = sqliterkOSMalloc(pager->pagesize); - if (!thePage->data) { - rc = SQLITERK_NOMEM; - goto sqliterkPageAcquire_Failed; - } - - size_t size = pager->pagesize; - rc = sqliterkOSRead(pager->file, (pageno - 1) * pager->pagesize, - thePage->data, &size); - if (rc != SQLITERK_OK) { - goto sqliterkPageAcquire_Failed; - } - - // For encrypted databases, decode page. - if (pager->codec) { - rc = sqliterkCryptoDecode(pager->codec, pageno, thePage->data); - if (rc != SQLITERK_OK) - goto sqliterkPageAcquire_Failed; - } - - // Check type - if (type == sqliterk_page_type_unknown) { - sqliterkParseInt(thePage->data, sqliterkPageHeaderOffset(thePage), 1, - &type); - switch (type) { - case sqliterk_page_type_interior_index: - case sqliterk_page_type_interior_table: - case sqliterk_page_type_leaf_index: - case sqliterk_page_type_leaf_table: - thePage->type = type; - break; - default: - thePage->type = sqliterk_page_type_unknown; - break; - } - } else { - thePage->type = type; - } - - *page = thePage; - return SQLITERK_OK; - -sqliterkPageAcquire_Failed: - if (thePage) { - sqliterkPageRelease(thePage); - } - *page = NULL; - return rc; -} - -int sqliterkPageRelease(sqliterk_page *page) -{ - if (!page) { - return SQLITERK_MISUSE; - } - if (page->data) { - sqliterkOSFree(page->data); - page->data = NULL; - } - sqliterkOSFree(page); - return SQLITERK_OK; -} - -// Ahead release the page data to save memory -int sqliterkPageClearData(sqliterk_page *page) -{ - if (!page) { - return SQLITERK_MISUSE; - } - if (page->data) { - sqliterkOSFree(page->data); - page->data = NULL; - } - return SQLITERK_OK; -} - -const unsigned char *sqliterkPageGetData(sqliterk_page *page) -{ - if (!page) { - return NULL; - } - return page->data; -} - -int sqliterkPagerGetSize(sqliterk_pager *pager) -{ - if (!pager) { - return 0; - } - return pager->pagesize; -} - -int sqliterkPagerGetUsableSize(sqliterk_pager *pager) -{ - if (!pager) { - return 0; - } - return pager->usableSize; -} - -int sqliterkPageGetPageno(sqliterk_page *page) -{ - if (!page) { - return 0; - } - return page->pageno; -} -sqliterk_page_type sqliterkPageGetType(sqliterk_page *page) -{ - if (!page) { - return sqliterk_page_type_unknown; - } - return page->type; -} - -int sqliterkPagenoHeaderOffset(int pageno) -{ - if (pageno == 1) { - return 100; - } - return 0; -} - -int sqliterkPageHeaderOffset(sqliterk_page *page) -{ - if (!page) { - return 0; - } - return sqliterkPagenoHeaderOffset(page->pageno); -} - -const char *sqliterkPageGetTypeName(sqliterk_page_type type) -{ - char *name; - switch (type) { - case sqliterk_page_type_interior_index: - name = "interior-index btree"; - break; - case sqliterk_page_type_interior_table: - name = "interior-table btree"; - break; - case sqliterk_page_type_leaf_index: - name = "leaf-index btree"; - break; - case sqliterk_page_type_leaf_table: - name = "leaf-table btree"; - break; - default: - name = "unknown page"; - break; - } - return name; -} - -void sqliterkPagerSetStatus(sqliterk_pager *pager, - int pageno, - sqliterk_status status) -{ - if (!pager || !pager->pagesStatus || - sqliterkPagerIsPagenoValid(pager, pageno) != SQLITERK_OK) { - return; - } - - pager->pagesStatus[pageno - 1] = status; - if (status == sqliterk_status_checked) - pager->integrity |= SQLITERK_INTEGRITY_DATA; -} - -sqliterk_status sqliterkPagerGetStatus(sqliterk_pager *pager, int pageno) -{ - if (!pager || !pager->pagesStatus || - sqliterkPagerIsPagenoValid(pager, pageno) != SQLITERK_OK) { - return sqliterk_status_invalid; - } - return pager->pagesStatus[pageno - 1]; -} - -int sqliterkPagerGetParsedPageCount(sqliterk_pager *pager) -{ - if (!pager || !pager->pagesStatus) { - return 0; - } - - int i, count = 0; - for (i = 0; i < pager->pagecount; i++) { - if (pager->pagesStatus[i] == sqliterk_status_checked) { - count++; - } - } - return count; -} - -int sqliterkPagerGetValidPageCount(sqliterk_pager *pager) -{ - if (!pager) { - return 0; - } - return pager->pagecount - pager->freepagecount; -} - -unsigned int sqliterkPagerGetIntegrity(sqliterk_pager *pager) -{ - if (!pager) { - return 0; - } - return pager->integrity; -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.h deleted file mode 100644 index 8acf5f85..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_pager.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_pager_h -#define sqliterk_pager_h - -#include "sqliterk_crypto.h" -#include - -// A legal state transfer is: -// unchecked --> checking -// checking --> invalid -// checking --> damaged -// checking --> checked -// checking --> discarded -// default status is unchecked -typedef enum { - sqliterk_status_invalid = -1, - sqliterk_status_unchecked = 0, - sqliterk_status_checking = 1, - sqliterk_status_damaged = 2, - sqliterk_status_discarded = 3, - sqliterk_status_checked = 4, -} sqliterk_status; - -// We are only concerned about the listed types. See https://www.sqlite.org/fileformat2.html#btree -typedef enum { - sqliterk_page_type_interior_index = 2, - sqliterk_page_type_interior_table = 5, - sqliterk_page_type_leaf_index = 10, - sqliterk_page_type_leaf_table = 13, - sqliterk_page_type_overflow = 1, - sqliterk_page_type_unknown = -1, -} sqliterk_page_type; - -// sqliterk_pager is the management class for all page in single db file -typedef struct sqliterk_pager sqliterk_pager; -// sqliterk_page is single page in db file, including its page data. But sometime, page data will be ahead release to save memory. -typedef struct sqliterk_page sqliterk_page; - -typedef struct sqliterk_file sqliterk_file; -typedef struct sqliterk_cipher_conf sqliterk_cipher_conf; -struct sqliterk_pager { - sqliterk_file *file; - sqliterk_status *pagesStatus; - int pagesize; - int freepagecount; - int reservedBytes; - int pagecount; - int usableSize; // pagesize-reservedBytes - unsigned int integrity; // integrity flags. - - sqliterk_codec *codec; // Codec context, implemented in SQLCipher library. -}; - -int sqliterkPagerOpen(const char *path, - const sqliterk_cipher_conf *cipher, - sqliterk_pager **pager); -int sqliterkPagerClose(sqliterk_pager *pager); -int sqliterkPagerGetPageCount(sqliterk_pager *pager); -int sqliterkPagerIsPagenoValid(sqliterk_pager *pager, int pageno); -int sqliterkPagerGetSize(sqliterk_pager *pager); -int sqliterkPagerGetUsableSize(sqliterk_pager *pager); - -void sqliterkPagerSetStatus(sqliterk_pager *pager, - int pageno, - sqliterk_status status); -sqliterk_status sqliterkPagerGetStatus(sqliterk_pager *pager, int pageno); -int sqliterkPagerGetParsedPageCount(sqliterk_pager *pager); -int sqliterkPagerGetValidPageCount(sqliterk_pager *pager); -unsigned int sqliterkPagerGetIntegrity(sqliterk_pager *pager); - -int sqliterkPageAcquire(sqliterk_pager *pager, - int pageno, - sqliterk_page **page); -int sqliterkPageAcquireOverflow(sqliterk_pager *pager, - int pageno, - sqliterk_page **page); -int sqliterkPageAcquireType(sqliterk_pager *pager, - int pageno, - sqliterk_page_type *type); -int sqliterkPageClearData(sqliterk_page *page); -int sqliterkPageRelease(sqliterk_page *page); - -int sqliterkPagenoHeaderOffset(int pageno); -int sqliterkPageHeaderOffset(sqliterk_page *page); - -const unsigned char *sqliterkPageGetData(sqliterk_page *page); - -int sqliterkPageGetPageno(sqliterk_page *page); -sqliterk_page_type sqliterkPageGetType(sqliterk_page *page); - -const char *sqliterkPageGetTypeName(sqliterk_page_type type); - -#endif /* sqliterk_pager_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.c deleted file mode 100644 index 7aa6f114..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_util.h" -#include "SQLiteRepairKit.h" -#include -#include -#include - -int sqliterkParseInt(const unsigned char *data, - int offset, - int length, - int *value) -{ - if (!value || length > sizeof(int)) { - return SQLITERK_MISUSE; - } - int64_t out; - int rc = sqliterkParseInt64(data, offset, length, &out); - if (rc != SQLITERK_OK) { - return rc; - } - *value = (int) out; - return SQLITERK_OK; -} - -int sqliterkParseInt64(const unsigned char *data, - int offset, - int length, - int64_t *value) -{ - if (!data || !value) - return SQLITERK_MISUSE; - - const unsigned char *p = data + offset; - int64_t out; - - switch (length) { - case 1: - out = (int8_t) p[0]; - break; - case 2: - out = (((int8_t) p[0]) * 256) | p[1]; - break; - case 3: - out = (((int8_t) p[0]) * 65536) | (p[1] << 8) | p[2]; - break; - case 4: - out = (((int8_t) p[0]) * 16777216) | (p[1] << 16) | (p[2] << 8) | - p[3]; - break; - case 6: - out = (((int8_t) p[0]) * 256) | p[1]; - out *= ((int64_t) 1) << 32; - out += - (((uint32_t) p[2]) << 24) | (p[3] << 16) | (p[4] << 8) | p[5]; - break; - case 8: - out = (((int8_t) p[0]) * 16777216) | (p[1] << 16) | (p[2] << 8) | - p[3]; - out *= ((int64_t) 1) << 32; - out += - (((uint32_t) p[4]) << 24) | (p[5] << 16) | (p[6] << 8) | p[7]; - break; - default: - return SQLITERK_MISUSE; - } - - *value = out; - return SQLITERK_OK; -} - -// Varint is a kind of huffman encoding value. For further informantion, -// see https://www.sqlite.org/fileformat2.html#varint -int sqliterkParseVarint(const unsigned char *data, - int offset, - int *length, - int *value) -{ - if (!value) { - return SQLITERK_MISUSE; - } - int64_t out; - int rc = sqliterkParseVarint64(data, offset, length, &out); - if (rc != SQLITERK_OK) { - return rc; - } - *value = (int) out; - return SQLITERK_OK; -} - -int sqliterkParseVarint64(const unsigned char *data, - int offset, - int *length, - int64_t *value) -{ - if (!data || !length || !value) { - return SQLITERK_MISUSE; - } - int64_t out = 0; - const unsigned char *begin = data + offset; - int i = 0; - while ((begin[i] & 0x80) && i < sqliterkGetMaxVarintLength()) { - out |= (begin[i] & 0x7f); - out = (out << 7); - i++; - if (i >= sqliterkGetMaxVarintLength()) { - return SQLITERK_DAMAGED; - } - } - out |= begin[i]; - *length = i + 1; - *value = out; - return SQLITERK_OK; -} - -int sqliterkGetMaxVarintLength() -{ - return 9; -} - -int sqliterkParseNumber(const unsigned char *data, int offset, double *value) -{ - if (!data || !value) { - return SQLITERK_MISUSE; - } - unsigned char out[8]; - const unsigned char *begin = data + offset; - int i; - for (i = 0; i < 8; i++) { - // All float values in SQLite is big-endian with 8 lengths. - // For further informantion, see [Record Format] chapter at - // https://www.sqlite.org/fileformat2.html - out[i] = begin[8 - 1 - i]; - } - memcpy(value, out, 8); - return SQLITERK_OK; -} - -const char *sqliterkGetResultCodeDescription(int result) -{ - switch (result) { - case SQLITERK_OK: - return "SQLITERK_OK"; - case SQLITERK_CANTOPEN: - return "SQLITERK_CANTOPEN"; - case SQLITERK_MISUSE: - return "SQLITERK_MISUSE"; - case SQLITERK_IOERR: - return "SQLITERK_IOERR"; - case SQLITERK_NOMEM: - return "SQLITERK_NOMEM"; - case SQLITERK_SHORT_READ: - return "SQLITERK_SHORT_READ"; - case SQLITERK_DAMAGED: - return "SQLITERK_DAMAGED"; - case SQLITERK_DISCARD: - return "SQLITERK_DISCARD"; - default: - break; - } - return "SQLITERK_UNKNOWN"; -} \ No newline at end of file diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.h deleted file mode 100644 index 92cd43c3..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_util.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_util_h -#define sqliterk_util_h - -#include - -int sqliterkParseInt(const unsigned char *data, - int offset, - int length, - int *value); -int sqliterkParseInt64(const unsigned char *data, - int offset, - int length, - int64_t *value); -int sqliterkParseVarint(const unsigned char *data, - int offset, - int *length, - int *value); -int sqliterkParseVarint64(const unsigned char *data, - int offset, - int *length, - int64_t *value); -int sqliterkParseNumber(const unsigned char *data, int offset, double *value); -int sqliterkGetMaxVarintLength(void); -const char *sqliterkGetResultCodeDescription(int result); - -#endif /* sqliterk_util_h */ diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.c b/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.c deleted file mode 100644 index 74a599bb..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 "sqliterk_values.h" -#include "SQLiteRepairKit.h" -#include "sqliterk_os.h" -#include "sqliterk_util.h" -#include -#include - -//declaration -static int sqliterkValuesAutoGrow(sqliterk_values *values); - -typedef int64_t sqliterk_integer; -typedef double sqliterk_number; -typedef struct sqliterk_text sqliterk_text; -struct sqliterk_text { - char *t; - int s; -}; -typedef struct sqliterk_binary sqliterk_binary; -struct sqliterk_binary { - void *b; - int s; -}; -typedef union sqliterk_any sqliterk_any; -union sqliterk_any { - sqliterk_integer integer; - sqliterk_number number; - sqliterk_text text; - sqliterk_binary binary; -}; - -struct sqliterk_value { - sqliterk_value_type type; - sqliterk_any any; -}; - -struct sqliterk_values { - int count; - int capacity; - sqliterk_value *values; -}; - -int sqliterkValuesAlloc(sqliterk_values **values) -{ - if (!values) { - return SQLITERK_MISUSE; - } - int rc = SQLITERK_OK; - sqliterk_values *theValues = sqliterkOSMalloc(sizeof(sqliterk_values)); - if (!theValues) { - rc = SQLITERK_NOMEM; - goto sqliterkValuesAlloc_Failed; - } - rc = sqliterkValuesAutoGrow(theValues); - if (rc != SQLITERK_OK) { - goto sqliterkValuesAlloc_Failed; - } - *values = theValues; - return SQLITERK_OK; -sqliterkValuesAlloc_Failed: - if (theValues) { - sqliterkValuesFree(theValues); - } - return rc; -} - -int sqliterkValuesFree(sqliterk_values *values) -{ - if (!values) { - return SQLITERK_MISUSE; - } - - int i; - for (i = 0; i < values->count; i++) { - sqliterk_value *value = &values->values[i]; - sqliterkValueClear(value); - } - values->count = 0; - if (values->values) { - sqliterkOSFree(values->values); - values->values = NULL; - } - values->capacity = 0; - sqliterkOSFree(values); - return SQLITERK_OK; -} - -int sqliterkValuesClear(sqliterk_values *values) -{ - if (!values) { - return SQLITERK_MISUSE; - } - - int i; - for (i = 0; i < values->count; i++) { - sqliterk_value *value = &values->values[i]; - sqliterkValueClear(value); - } - values->count = 0; - return SQLITERK_OK; -} - -static int sqliterkValuesAutoGrow(sqliterk_values *values) -{ - if (!values) { - return SQLITERK_MISUSE; - } - if (values->count >= values->capacity) { - int oldCapacity = values->capacity; - int newCapacity; - if (oldCapacity <= 0) { - //init for 4 - newCapacity = 4; - } else if (oldCapacity > 8 * 1024 * 1024) { - newCapacity = oldCapacity + 8 * 1024 * 1024; - } else { - newCapacity = oldCapacity * 2; - } - sqliterk_value *newValues = - sqliterkOSMalloc(sizeof(sqliterk_value) * (newCapacity + 1)); - if (!newValues) { - return SQLITERK_NOMEM; - } - if (values->values) { - memcpy(newValues, values->values, - sizeof(sqliterk_value) * oldCapacity); - sqliterkOSFree(values->values); - } - values->values = newValues; - values->capacity = newCapacity; - } - return SQLITERK_OK; -} - -int sqliterkValuesGetCount(sqliterk_values *values) -{ - if (!values) { - return 0; - } - return values->count; -} - -sqliterk_value_type sqliterkValuesGetType(sqliterk_values *values, int index) -{ - if (values && index < sqliterkValuesGetCount(values)) { - return values->values[index].type; - } - return sqliterk_value_type_null; -} - -int64_t sqliterkValuesGetInteger64(sqliterk_values *values, int index) -{ - int64_t out = 0; - if (values && index < sqliterkValuesGetCount(values)) { - sqliterk_value *value = &values->values[index]; - switch (sqliterkValuesGetType(values, index)) { - case sqliterk_value_type_integer: - out = (int64_t)(value->any.integer); - break; - case sqliterk_value_type_number: - out = (int64_t)(value->any.number); - break; - case sqliterk_value_type_text: - out = atol(value->any.text.t); - break; - default: - break; - } - } - return out; -} - -int sqliterkValuesGetInteger(sqliterk_values *values, int index) -{ - return (int) sqliterkValuesGetInteger64(values, index); -} - -double sqliterkValuesGetNumber(sqliterk_values *values, int index) -{ - double out = 0; - if (values && index < sqliterkValuesGetCount(values)) { - sqliterk_value *value = &values->values[index]; - switch (sqliterkValuesGetType(values, index)) { - case sqliterk_value_type_integer: - out = (double) (value->any.integer); - break; - case sqliterk_value_type_number: - out = (double) (value->any.number); - break; - case sqliterk_value_type_text: - out = atof(value->any.text.t); - break; - default: - break; - } - } - return out; -} - -const char *sqliterkValuesGetText(sqliterk_values *values, int index) -{ - char *out = NULL; - if (values && index < sqliterkValuesGetCount(values)) { - sqliterk_value *value = &values->values[index]; - switch (value->type) { - case sqliterk_value_type_text: - out = value->any.text.t; - break; - default: - break; - } - } - return out; -} - -const void *sqliterkValuesGetBinary(sqliterk_values *values, int index) -{ - void *out = NULL; - if (values && index < sqliterkValuesGetCount(values)) { - sqliterk_value *value = &values->values[index]; - switch (value->type) { - case sqliterk_value_type_binary: - out = value->any.binary.b; - break; - default: - break; - } - } - return out; -} - -int sqliterkValuesGetBytes(sqliterk_values *values, int index) -{ - int out = 0; - if (values && index < sqliterkValuesGetCount(values)) { - sqliterk_value *value = &values->values[index]; - switch (value->type) { - case sqliterk_value_type_binary: - out = value->any.binary.s; - break; - case sqliterk_value_type_text: - out = value->any.text.s; - break; - default: - break; - } - } - return out; -} - -int sqliterkValuesAddInteger64(sqliterk_values *values, int64_t i) -{ - if (!values) { - return SQLITERK_MISUSE; - } - int rc = sqliterkValuesAutoGrow(values); - if (rc != SQLITERK_OK) { - return rc; - } - sqliterk_value *value = &values->values[values->count]; - value->type = sqliterk_value_type_integer; - value->any.integer = i; - values->count++; - return SQLITERK_OK; -} - -int sqliterkValuesAddInteger(sqliterk_values *values, int i) -{ - return sqliterkValuesAddInteger64(values, i); -} - -int sqliterkValuesAddNumber(sqliterk_values *values, double d) -{ - if (!values) { - return SQLITERK_MISUSE; - } - int rc = sqliterkValuesAutoGrow(values); - if (rc != SQLITERK_OK) { - return rc; - } - sqliterk_value *value = &values->values[values->count]; - value->type = sqliterk_value_type_number; - value->any.number = d; - values->count++; - return SQLITERK_OK; -} - -int sqliterkValuesAddText(sqliterk_values *values, const char *t) -{ - return sqliterkValuesAddNoTerminatorText(values, t, (int) strlen(t)); -} - -int sqliterkValuesAddNoTerminatorText(sqliterk_values *values, - const char *t, - const int s) -{ - if (!values || !t) { - return SQLITERK_MISUSE; - } - int rc = sqliterkValuesAutoGrow(values); - if (rc != SQLITERK_OK) { - return rc; - } - sqliterk_value *value = &values->values[values->count]; - value->type = sqliterk_value_type_text; - value->any.text.s = s; - value->any.text.t = sqliterkOSMalloc(sizeof(char) * (s + 1)); - if (!value->any.text.t) { - rc = SQLITERK_NOMEM; - goto sqliterkValuesAddNoTerminatorText_Failed; - } - memcpy(value->any.text.t, t, s); - value->any.text.t[s] = '\0'; - values->count++; - return SQLITERK_OK; - -sqliterkValuesAddNoTerminatorText_Failed: - sqliterkValueClear(value); - return rc; -} - -int sqliterkValuesAddBinary(sqliterk_values *values, const void *b, const int s) -{ - if (!values || !b) { - return SQLITERK_MISUSE; - } - int rc = sqliterkValuesAutoGrow(values); - if (rc != SQLITERK_OK) { - return rc; - } - sqliterk_value *value = &values->values[values->count]; - value->type = sqliterk_value_type_binary; - value->any.binary.s = s; - value->any.binary.b = sqliterkOSMalloc(s); - if (!value->any.binary.b) { - return SQLITERK_NOMEM; - } - memcpy(value->any.binary.b, b, s); - values->count++; - return SQLITERK_OK; -} - -int sqliterkValuesAddNull(sqliterk_values *values) -{ - if (!values) { - return SQLITERK_MISUSE; - } - int rc = sqliterkValuesAutoGrow(values); - if (rc != SQLITERK_OK) { - return rc; - } - sqliterk_value *value = &values->values[values->count]; - value->type = sqliterk_value_type_null; - values->count++; - return SQLITERK_OK; -} - -int sqliterkValueClear(sqliterk_value *value) -{ - if (!value) { - return SQLITERK_MISUSE; - } - - switch (value->type) { - case sqliterk_value_type_text: - if (value->any.text.t) { - sqliterkOSFree(value->any.text.t); - value->any.text.t = NULL; - } - break; - case sqliterk_value_type_binary: - if (value->any.binary.b) { - sqliterkOSFree(value->any.binary.b); - value->any.binary.b = NULL; - } - break; - default: - break; - } - - value->type = sqliterk_value_type_null; - return SQLITERK_OK; -} diff --git a/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.h b/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.h deleted file mode 100644 index fb5af873..00000000 --- a/Example/Pods/SQLiteRepairKit/repair/sqliterk_values.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 sqliterk_values_h -#define sqliterk_values_h - -#include "SQLiteRepairKit.h" -#include - -// sqliterk_values is a kind of [Any] array. -typedef struct sqliterk_values sqliterk_values; -typedef struct sqliterk_value sqliterk_value; - -int sqliterkValuesAlloc(sqliterk_values **values); -int sqliterkValuesFree(sqliterk_values *values); -int sqliterkValuesClear(sqliterk_values *values); - -int sqliterkValuesAddInteger(sqliterk_values *values, int i); -int sqliterkValuesAddInteger64(sqliterk_values *values, int64_t i); -int sqliterkValuesAddNumber(sqliterk_values *values, double d); -int sqliterkValuesAddText(sqliterk_values *values, const char *t); -int sqliterkValuesAddNoTerminatorText(sqliterk_values *values, - const char *t, - const int s); -int sqliterkValuesAddBinary(sqliterk_values *values, - const void *b, - const int s); -int sqliterkValuesAddNull(sqliterk_values *values); - -int sqliterkValuesGetCount(sqliterk_values *values); -sqliterk_value_type sqliterkValuesGetType(sqliterk_values *values, int index); -int sqliterkValuesGetInteger(sqliterk_values *values, int index); -int64_t sqliterkValuesGetInteger64(sqliterk_values *values, int index); -double sqliterkValuesGetNumber(sqliterk_values *values, int index); -const char *sqliterkValuesGetText(sqliterk_values *values, int index); -const void *sqliterkValuesGetBinary(sqliterk_values *values, int index); -int sqliterkValuesGetBytes(sqliterk_values *values, int index); - -int sqliterkValueClear(sqliterk_value *value); - -#endif /* sqliterk_values_h */ diff --git a/Example/Pods/SnapKit/README.md b/Example/Pods/SnapKit/README.md index b36df7a5..e1be307f 100644 --- a/Example/Pods/SnapKit/README.md +++ b/Example/Pods/SnapKit/README.md @@ -22,7 +22,7 @@ SnapKit is a DSL to make Auto Layout easy on both iOS and OS X. ## Requirements -- iOS 10.0+ / Mac OS X 10.12+ / tvOS 10.0+ +- iOS 12.0+ / Mac OS X 10.13+ / tvOS 10.0+ - Xcode 10.0+ - Swift 4.0+ @@ -59,7 +59,7 @@ platform :ios, '10.0' use_frameworks! target '' do - pod 'SnapKit', '~> 5.6.0' + pod 'SnapKit', '~> 5.7.0' end ``` diff --git a/Example/Pods/SnapKit/Sources/Constraint.swift b/Example/Pods/SnapKit/Sources/Constraint.swift index 37409b3b..b8901522 100644 --- a/Example/Pods/SnapKit/Sources/Constraint.swift +++ b/Example/Pods/SnapKit/Sources/Constraint.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -101,7 +101,7 @@ public final class Constraint { for layoutFromAttribute in layoutFromAttributes { // get layout to attribute let layoutToAttribute: LayoutAttribute - #if os(iOS) || os(tvOS) + #if canImport(UIKit) if layoutToAttributes.count > 0 { if self.from.attributes == .edges && self.to.attributes == .margins { switch layoutFromAttribute { @@ -245,7 +245,7 @@ public final class Constraint { return self } - #if os(iOS) || os(tvOS) + #if canImport(UIKit) @discardableResult @available(iOS 11.0, tvOS 11.0, *) public func update(inset: ConstraintDirectionalInsetTarget) -> Constraint { diff --git a/Example/Pods/SnapKit/Sources/ConstraintAttributes.swift b/Example/Pods/SnapKit/Sources/ConstraintAttributes.swift index 408308b8..c1a79c23 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintAttributes.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintAttributes.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -152,7 +152,7 @@ internal struct ConstraintAttributes : OptionSet, ExpressibleByIntegerLiteral { attrs.append(.lastBaseline) } - #if os(iOS) || os(tvOS) + #if canImport(UIKit) if (self.contains(ConstraintAttributes.firstBaseline)) { attrs.append(.firstBaseline) } diff --git a/Example/Pods/SnapKit/Sources/ConstraintConfig.swift b/Example/Pods/SnapKit/Sources/ConstraintConfig.swift index 2746b7d2..9bd0f23c 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintConfig.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintConfig.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection #else diff --git a/Example/Pods/SnapKit/Sources/ConstraintConstantTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintConstantTarget.swift index 7f549078..e16f5033 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintConstantTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintConstantTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -40,7 +40,7 @@ extension CGSize: ConstraintConstantTarget { extension ConstraintInsets: ConstraintConstantTarget { } -#if os(iOS) || os(tvOS) +#if canImport(UIKit) @available(iOS 11.0, tvOS 11.0, *) extension ConstraintDirectionalInsets: ConstraintConstantTarget { } @@ -80,7 +80,7 @@ extension ConstraintConstantTarget { } if let value = self as? CGPoint { - #if os(iOS) || os(tvOS) + #if canImport(UIKit) switch layoutAttribute { case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins: return value.x @@ -110,7 +110,7 @@ extension ConstraintConstantTarget { } if let value = self as? ConstraintInsets { - #if os(iOS) || os(tvOS) + #if canImport(UIKit) switch layoutAttribute { case .left, .leftMargin: return value.left @@ -171,7 +171,7 @@ extension ConstraintConstantTarget { #endif } - #if os(iOS) || os(tvOS) + #if canImport(UIKit) if #available(iOS 11.0, tvOS 11.0, *), let value = self as? ConstraintDirectionalInsets { switch layoutAttribute { case .left, .leftMargin: diff --git a/Example/Pods/SnapKit/Sources/ConstraintDSL.swift b/Example/Pods/SnapKit/Sources/ConstraintDSL.swift index 20f153da..5683b7f9 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintDSL.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintDSL.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintDescription.swift b/Example/Pods/SnapKit/Sources/ConstraintDescription.swift index 3521f9f9..b9d476c4 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintDescription.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintDescription.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift index 955aec35..4c3c4185 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift @@ -21,13 +21,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) public protocol ConstraintDirectionalInsetTarget: ConstraintConstantTarget { } diff --git a/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift b/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift index ada8ed5b..056b5c83 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift @@ -21,14 +21,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) @available(iOS 11.0, tvOS 11.0, *) public typealias ConstraintDirectionalInsets = NSDirectionalEdgeInsets #endif diff --git a/Example/Pods/SnapKit/Sources/ConstraintInsetTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintInsetTarget.swift index ba8a0f3e..43c02209 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintInsetTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintInsetTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintInsets.swift b/Example/Pods/SnapKit/Sources/ConstraintInsets.swift index 738ca055..64d781d9 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintInsets.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintInsets.swift @@ -21,14 +21,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) public typealias ConstraintInsets = UIEdgeInsets #else public typealias ConstraintInsets = NSEdgeInsets diff --git a/Example/Pods/SnapKit/Sources/ConstraintItem.swift b/Example/Pods/SnapKit/Sources/ConstraintItem.swift index a342c1d9..2f92221a 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintItem.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintItem.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift index d429e0cc..e9fd9b34 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #endif diff --git a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift index e3e50c89..fd895569 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift @@ -21,14 +21,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) @available(iOS 9.0, *) public typealias ConstraintLayoutGuide = UILayoutGuide #else diff --git a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift index 0007819c..7e78261e 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift b/Example/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift index e92e9fbc..085f5cd4 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift @@ -21,14 +21,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) @available(iOS 8.0, *) public typealias ConstraintLayoutSupport = UILayoutSupport #else diff --git a/Example/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift b/Example/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift index 5d6ae899..71e11584 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMaker.swift b/Example/Pods/SnapKit/Sources/ConstraintMaker.swift index 50d7402b..7c352f64 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMaker.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMaker.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerEditable.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerEditable.swift index 4869bc28..0e08e384 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerEditable.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerEditable.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -53,7 +53,7 @@ public class ConstraintMakerEditable: ConstraintMakerPrioritizable { return self } - #if os(iOS) || os(tvOS) + #if canImport(UIKit) @discardableResult @available(iOS 11.0, tvOS 11.0, *) public func inset(_ amount: ConstraintDirectionalInsetTarget) -> ConstraintMakerEditable { diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerExtendable.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerExtendable.swift index d8346493..b30688ea 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerExtendable.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerExtendable.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift index 4e1379e2..83424762 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerPrioritizable.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerPrioritizable.swift index 5af53033..05451e64 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerPrioritizable.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerPrioritizable.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable+Extensions.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable+Extensions.swift index 63100d7c..bfde2725 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable+Extensions.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable+Extensions.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -47,7 +47,7 @@ extension ConstraintMakerRelatable { } @discardableResult - public func greaterThanOrEqualTo(_ closure: (ConstraintView) -> T, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable { + public func greaterThanOrEqualToSuperview(_ closure: (ConstraintView) -> T, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable { guard let other = self.description.item.superview else { fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.") } diff --git a/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable.swift b/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable.swift index 78895323..0a3d5ee2 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMakerRelatable.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift index 6fecd33e..ac537ba2 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift index bd9e0a1e..6ec11075 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintPriority.swift b/Example/Pods/SnapKit/Sources/ConstraintPriority.swift index f9dab162..bf906930 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintPriority.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintPriority.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift index 064f750b..1aa701ef 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -74,7 +74,7 @@ extension CGFloat: ConstraintPriorityTarget { } -#if os(iOS) || os(tvOS) +#if canImport(UIKit) extension UILayoutPriority: ConstraintPriorityTarget { public var constraintPriorityTargetValue: Float { diff --git a/Example/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift b/Example/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift index d517a61e..df04464e 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -55,7 +55,7 @@ extension CGPoint: ConstraintRelatableTarget { extension ConstraintInsets: ConstraintRelatableTarget { } -#if os(iOS) || os(tvOS) +#if canImport(UIKit) @available(iOS 11.0, tvOS 11.0, *) extension ConstraintDirectionalInsets: ConstraintRelatableTarget { } diff --git a/Example/Pods/SnapKit/Sources/ConstraintRelation.swift b/Example/Pods/SnapKit/Sources/ConstraintRelation.swift index 446aaf76..643d4992 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintRelation.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintRelation.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintView+Extensions.swift b/Example/Pods/SnapKit/Sources/ConstraintView+Extensions.swift index e0f71c1a..1225c042 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintView+Extensions.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintView+Extensions.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/ConstraintView.swift b/Example/Pods/SnapKit/Sources/ConstraintView.swift index 6ff8a76e..12033007 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintView.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintView.swift @@ -21,14 +21,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit #endif -#if os(iOS) || os(tvOS) +#if canImport(UIKit) public typealias ConstraintView = UIView #else public typealias ConstraintView = NSView diff --git a/Example/Pods/SnapKit/Sources/ConstraintViewDSL.swift b/Example/Pods/SnapKit/Sources/ConstraintViewDSL.swift index a0187f97..8567e547 100644 --- a/Example/Pods/SnapKit/Sources/ConstraintViewDSL.swift +++ b/Example/Pods/SnapKit/Sources/ConstraintViewDSL.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/Debugging.swift b/Example/Pods/SnapKit/Sources/Debugging.swift index a78579ab..f4120b2e 100644 --- a/Example/Pods/SnapKit/Sources/Debugging.swift +++ b/Example/Pods/SnapKit/Sources/Debugging.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit @@ -89,7 +89,7 @@ private func descriptionForRelation(_ relation: LayoutRelation) -> String { } private func descriptionForAttribute(_ attribute: LayoutAttribute) -> String { - #if os(iOS) || os(tvOS) + #if canImport(UIKit) switch attribute { case .notAnAttribute: return "notAnAttribute" case .top: return "top" diff --git a/Example/Pods/SnapKit/Sources/LayoutConstraint.swift b/Example/Pods/SnapKit/Sources/LayoutConstraint.swift index 5425ea8e..607616d9 100644 --- a/Example/Pods/SnapKit/Sources/LayoutConstraint.swift +++ b/Example/Pods/SnapKit/Sources/LayoutConstraint.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/LayoutConstraintItem.swift b/Example/Pods/SnapKit/Sources/LayoutConstraintItem.swift index 9b61d18c..4f41b5d6 100644 --- a/Example/Pods/SnapKit/Sources/LayoutConstraintItem.swift +++ b/Example/Pods/SnapKit/Sources/LayoutConstraintItem.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #else import AppKit diff --git a/Example/Pods/SnapKit/Sources/Typealiases.swift b/Example/Pods/SnapKit/Sources/Typealiases.swift index ded96ccd..c0e6982e 100644 --- a/Example/Pods/SnapKit/Sources/Typealiases.swift +++ b/Example/Pods/SnapKit/Sources/Typealiases.swift @@ -23,7 +23,7 @@ import Foundation -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #if swift(>=4.2) typealias LayoutRelation = NSLayoutConstraint.Relation diff --git a/Example/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift b/Example/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift index 8e7644cf..801cc3cd 100644 --- a/Example/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift +++ b/Example/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift @@ -21,7 +21,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#if os(iOS) || os(tvOS) +#if canImport(UIKit) import UIKit #endif diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.markdown index 39ad458b..0311c32f 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.markdown +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.markdown @@ -122,425 +122,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## SQLiteRepairKit - -Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. - - ## SmartCodable Copyright (c) 2023 mancong@bertadata.com @@ -586,451 +167,4 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -## WCDB.swift - -Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. - - -## WCDBOptimizedSQLCipher - -Copyright (c) 2008, ZETETIC LLC -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of the ZETETIC LLC 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 ZETETIC LLC ''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 ZETETIC LLC 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. - Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.plist index 5a9b2a82..16d212b6 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.plist +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-acknowledgements.plist @@ -157,431 +157,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Type PSGroupSpecifier - - FooterText - Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. - - License - BSD - Title - SQLiteRepairKit - Type - PSGroupSpecifier - FooterText Copyright (c) 2023 mancong@bertadata.com <mancong@bertadata.com> @@ -640,465 +215,6 @@ THE SOFTWARE. Type PSGroupSpecifier - - FooterText - Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. - - License - BSD - Title - WCDB.swift - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2008, ZETETIC LLC -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of the ZETETIC LLC 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 ZETETIC LLC ''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 ZETETIC LLC 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. - - License - BSD - Title - WCDBOptimizedSQLCipher - Type - PSGroupSpecifier - FooterText Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-frameworks.sh index 68a60e6f..318ab624 100755 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-frameworks.sh +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example-frameworks.sh @@ -180,22 +180,16 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/BTPrint/BTPrint.framework" install_framework "${BUILT_PRODUCTS_DIR}/CleanJSON/CleanJSON.framework" install_framework "${BUILT_PRODUCTS_DIR}/HandyJSON/HandyJSON.framework" - install_framework "${BUILT_PRODUCTS_DIR}/SQLiteRepairKit/sqliterk.framework" install_framework "${BUILT_PRODUCTS_DIR}/SmartCodable/SmartCodable.framework" install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework" - install_framework "${BUILT_PRODUCTS_DIR}/WCDB.swift/WCDBSwift.framework" - install_framework "${BUILT_PRODUCTS_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then install_framework "${BUILT_PRODUCTS_DIR}/BTBubble/BTBubble.framework" install_framework "${BUILT_PRODUCTS_DIR}/BTPrint/BTPrint.framework" install_framework "${BUILT_PRODUCTS_DIR}/CleanJSON/CleanJSON.framework" install_framework "${BUILT_PRODUCTS_DIR}/HandyJSON/HandyJSON.framework" - install_framework "${BUILT_PRODUCTS_DIR}/SQLiteRepairKit/sqliterk.framework" install_framework "${BUILT_PRODUCTS_DIR}/SmartCodable/SmartCodable.framework" install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework" - install_framework "${BUILT_PRODUCTS_DIR}/WCDB.swift/WCDBSwift.framework" - install_framework "${BUILT_PRODUCTS_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.debug.xcconfig index 083f5af3..6202c2b7 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.debug.xcconfig @@ -1,11 +1,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit/sqliterk.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift/WCDBSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "Foundation" -framework "HandyJSON" -framework "Security" -framework "SmartCodable" -framework "SnapKit" -framework "WCDBSwift" -framework "sqlcipher" -framework "sqliterk" +OTHER_LDFLAGS = $(inherited) -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "HandyJSON" -framework "SmartCodable" -framework "SnapKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.release.xcconfig index 083f5af3..6202c2b7 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Example/Pods-SmartCodable_Example.release.xcconfig @@ -1,11 +1,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit/sqliterk.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift/WCDBSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "Foundation" -framework "HandyJSON" -framework "Security" -framework "SmartCodable" -framework "SnapKit" -framework "WCDBSwift" -framework "sqlcipher" -framework "sqliterk" +OTHER_LDFLAGS = $(inherited) -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "HandyJSON" -framework "SmartCodable" -framework "SnapKit" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.debug.xcconfig index 7d75be6a..4f120caa 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.debug.xcconfig @@ -1,11 +1,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit/sqliterk.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift/WCDBSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "HandyJSON" -framework "QuartzCore" -framework "Security" -framework "SmartCodable" -framework "SnapKit" -framework "UIKit" -framework "WCDBSwift" -framework "XCTest" -framework "sqlcipher" -framework "sqliterk" +OTHER_LDFLAGS = $(inherited) -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "HandyJSON" -framework "QuartzCore" -framework "SmartCodable" -framework "SnapKit" -framework "UIKit" -framework "XCTest" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.release.xcconfig index 7d75be6a..4f120caa 100644 --- a/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-SmartCodable_Tests/Pods-SmartCodable_Tests.release.xcconfig @@ -1,11 +1,11 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit/sqliterk.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift/WCDBSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher/sqlcipher.framework/Headers" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BTBubble/BTBubble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BTPrint/BTPrint.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CleanJSON/CleanJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HandyJSON/HandyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SmartCodable/SmartCodable.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "HandyJSON" -framework "QuartzCore" -framework "Security" -framework "SmartCodable" -framework "SnapKit" -framework "UIKit" -framework "WCDBSwift" -framework "XCTest" -framework "sqlcipher" -framework "sqliterk" +OTHER_LDFLAGS = $(inherited) -framework "BTBubble" -framework "BTPrint" -framework "CleanJSON" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "HandyJSON" -framework "QuartzCore" -framework "SmartCodable" -framework "SnapKit" -framework "UIKit" -framework "XCTest" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-dummy.m b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-dummy.m deleted file mode 100644 index 4dc69a68..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_SQLiteRepairKit : NSObject -@end -@implementation PodsDummy_SQLiteRepairKit -@end diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-umbrella.h b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-umbrella.h deleted file mode 100644 index 0c4cbb59..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-umbrella.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "SQLiteRepairKit.h" - -FOUNDATION_EXPORT double sqliterkVersionNumber; -FOUNDATION_EXPORT const unsigned char sqliterkVersionString[]; - diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.debug.xcconfig b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.debug.xcconfig deleted file mode 100644 index 8dcb8ecc..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.debug.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_CXX_LANGUAGE_STANDARD = gnu++0x -CLANG_CXX_LIBRARY = libc++ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SQLITE_HAS_CODEC WCDB_BUILTIN_SQLCIPHER -LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)/usr/lib/system -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "Foundation" -framework "Security" -framework "sqlcipher" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/SQLiteRepairKit -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap deleted file mode 100644 index 72f295f7..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module sqliterk { - umbrella header "SQLiteRepairKit-umbrella.h" - - export * - module * { export * } -} diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.release.xcconfig b/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.release.xcconfig deleted file mode 100644 index 8dcb8ecc..00000000 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit.release.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_CXX_LANGUAGE_STANDARD = gnu++0x -CLANG_CXX_LIBRARY = libc++ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SQLITE_HAS_CODEC WCDB_BUILTIN_SQLCIPHER -LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)/usr/lib/system -OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "Foundation" -framework "Security" -framework "sqlcipher" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/SQLiteRepairKit -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/SmartCodable/SmartCodable-Info.plist b/Example/Pods/Target Support Files/SmartCodable/SmartCodable-Info.plist index e8e15e03..fee5e016 100644 --- a/Example/Pods/Target Support Files/SmartCodable/SmartCodable-Info.plist +++ b/Example/Pods/Target Support Files/SmartCodable/SmartCodable-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.4.6 + 4.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-Info.plist b/Example/Pods/Target Support Files/SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist similarity index 80% rename from Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-Info.plist rename to Example/Pods/Target Support Files/SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist index 9bba304e..d6be5716 100644 --- a/Example/Pods/Target Support Files/SQLiteRepairKit/SQLiteRepairKit-Info.plist +++ b/Example/Pods/Target Support Files/SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist @@ -4,8 +4,6 @@ CFBundleDevelopmentRegion ${PODS_DEVELOPMENT_LANGUAGE} - CFBundleExecutable - ${EXECUTABLE_NAME} CFBundleIdentifier ${PRODUCT_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion @@ -13,13 +11,13 @@ CFBundleName ${PRODUCT_NAME} CFBundlePackageType - FMWK + BNDL CFBundleShortVersionString - 1.3.0 + 5.7.1 CFBundleSignature ???? CFBundleVersion - ${CURRENT_PROJECT_VERSION} + 1 NSPrincipalClass diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-Info.plist b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-Info.plist deleted file mode 100644 index dc59427d..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - ${PODS_DEVELOPMENT_LANGUAGE} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.1.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-dummy.m b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-dummy.m deleted file mode 100644 index c33cf404..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_WCDB_swift : NSObject -@end -@implementation PodsDummy_WCDB_swift -@end diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-prefix.pch b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-umbrella.h b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-umbrella.h deleted file mode 100644 index 70388d1e..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift-umbrella.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "SQLite-Bridging.h" -#import "WCDB-Bridging.h" - -FOUNDATION_EXPORT double WCDBSwiftVersionNumber; -FOUNDATION_EXPORT const unsigned char WCDBSwiftVersionString[]; - diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.debug.xcconfig b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.debug.xcconfig deleted file mode 100644 index 591d41e6..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.debug.xcconfig +++ /dev/null @@ -1,25 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SQLITE_HAS_CODEC WCDB_BUILTIN_SQLCIPHER -HEADER_SEARCH_PATHS = $(inherited) ${PODS_ROOT}/WCDBSwift -LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)/usr/lib/system -OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "Security" -framework "sqlcipher" -framework "sqliterk" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG -OTHER_SWIFT_FLAGS[config=Debug][sdk=iphoneos*] = -D WCDB_IOS -D DEBUG -OTHER_SWIFT_FLAGS[config=Debug][sdk=iphonesimulator*] = -D WCDB_IOS -D DEBUG -OTHER_SWIFT_FLAGS[config=Release][sdk=iphoneos*] = -D WCDB_IOS -OTHER_SWIFT_FLAGS[config=Release][sdk=iphonesimulator*] = -D WCDB_IOS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/WCDB.swift -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -SWIFT_WHOLE_MODULE_OPTIMIZATION = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.modulemap b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.modulemap deleted file mode 100644 index 00a891cb..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module WCDBSwift { - umbrella header "WCDB.swift-umbrella.h" - - export * - module * { export * } -} diff --git a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.release.xcconfig b/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.release.xcconfig deleted file mode 100644 index 591d41e6..00000000 --- a/Example/Pods/Target Support Files/WCDB.swift/WCDB.swift.release.xcconfig +++ /dev/null @@ -1,25 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WCDB.swift -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SQLiteRepairKit" "${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 SQLITE_HAS_CODEC WCDB_BUILTIN_SQLCIPHER -HEADER_SEARCH_PATHS = $(inherited) ${PODS_ROOT}/WCDBSwift -LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)/usr/lib/system -OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "Security" -framework "sqlcipher" -framework "sqliterk" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG -OTHER_SWIFT_FLAGS[config=Debug][sdk=iphoneos*] = -D WCDB_IOS -D DEBUG -OTHER_SWIFT_FLAGS[config=Debug][sdk=iphonesimulator*] = -D WCDB_IOS -D DEBUG -OTHER_SWIFT_FLAGS[config=Release][sdk=iphoneos*] = -D WCDB_IOS -OTHER_SWIFT_FLAGS[config=Release][sdk=iphonesimulator*] = -D WCDB_IOS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/WCDB.swift -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -SWIFT_WHOLE_MODULE_OPTIMIZATION = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist deleted file mode 100644 index 9bba304e..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - ${PODS_DEVELOPMENT_LANGUAGE} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.3.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-dummy.m b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-dummy.m deleted file mode 100644 index 7d48e077..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_WCDBOptimizedSQLCipher : NSObject -@end -@implementation PodsDummy_WCDBOptimizedSQLCipher -@end diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-umbrella.h b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-umbrella.h deleted file mode 100644 index c06c5219..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher-umbrella.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - -#import "sqlite3.h" -#import "fts3_tokenizer.h" - -FOUNDATION_EXPORT double sqlcipherVersionNumber; -FOUNDATION_EXPORT const unsigned char sqlcipherVersionString[]; - diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.debug.xcconfig b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.debug.xcconfig deleted file mode 100644 index f39fedc7..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.debug.xcconfig +++ /dev/null @@ -1,21 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_WARN_COMMA = NO -CLANG_WARN_CONSTANT_CONVERSION = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CLANG_WARN_STRICT_PROTOTYPES = NO -CLANG_WARN_UNREACHABLE_CODE = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 NDEBUG=1 SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_API_ARMOR SQLITE_OMIT_BUILTIN_TEST SQLITE_OMIT_AUTORESET SQLITE_ENABLE_UPDATE_DELETE_LIMIT SQLITE_ENABLE_RTREE SQLITE_ENABLE_LOCKING_STYLE=1 SQLITE_SYSTEM_MALLOC SQLITE_OMIT_LOAD_EXTENSION SQLITE_CORE SQLITE_THREADSAFE=2 SQLITE_DEFAULT_CACHE_SIZE=-2000 SQLITE_DEFAULT_PAGE_SIZE=4096 SQLITE_HAS_CODEC SQLCIPHER_CRYPTO_CC USE_PREAD=1 SQLITE_TEMP_STORE=2 SQLCIPHER_PREPROCESSED HAVE_USLEEP HAVE_UTIME SQLITE_MALLOC_SOFT_LIMIT=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_ENABLE_COLUMN_METADATA SQLITE_DEFAULT_WAL_SYNCHRONOUS=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED SQLITE_OMIT_PROGRESS_CALLBACK SQLITE_OMIT_SHARED_CACHE OMIT_MEMLOCK SQLITE_ENABLE_FTS3_TOKENIZER SQLITE_ENABLE_DBSTAT_VTAB SQLITE_WCDB_CHECKPOINT_HANDLER SQLITE_MMAP_READWRITE SQLITE_WCDB_API_NO_HIDDEN SQLITE_ENABLE_FTS5 SQLITE_WCDB_DIRTY_PAGE_COUNT SQLITE_PRINT_BUF_SIZE=256 SQLITE_MAX_ATTACHED=64 SQLITE_USE_ALLOCA SQLITE_WCDB_SIGNAL_RETRY -GCC_WARN_64_TO_32_BIT_CONVERSION = NO -GCC_WARN_UNUSED_FUNCTION = NO -GCC_WARN_UNUSED_VARIABLE = NO -OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "Security" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/WCDBOptimizedSQLCipher -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap deleted file mode 100644 index fd61d19c..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module sqlcipher { - umbrella header "WCDBOptimizedSQLCipher-umbrella.h" - - export * - module * { export * } -} diff --git a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.release.xcconfig b/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.release.xcconfig deleted file mode 100644 index f39fedc7..00000000 --- a/Example/Pods/Target Support Files/WCDBOptimizedSQLCipher/WCDBOptimizedSQLCipher.release.xcconfig +++ /dev/null @@ -1,21 +0,0 @@ -APPLICATION_EXTENSION_API_ONLY = YES -CLANG_WARN_COMMA = NO -CLANG_WARN_CONSTANT_CONVERSION = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CLANG_WARN_STRICT_PROTOTYPES = NO -CLANG_WARN_UNREACHABLE_CODE = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WCDBOptimizedSQLCipher -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 NDEBUG=1 SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_API_ARMOR SQLITE_OMIT_BUILTIN_TEST SQLITE_OMIT_AUTORESET SQLITE_ENABLE_UPDATE_DELETE_LIMIT SQLITE_ENABLE_RTREE SQLITE_ENABLE_LOCKING_STYLE=1 SQLITE_SYSTEM_MALLOC SQLITE_OMIT_LOAD_EXTENSION SQLITE_CORE SQLITE_THREADSAFE=2 SQLITE_DEFAULT_CACHE_SIZE=-2000 SQLITE_DEFAULT_PAGE_SIZE=4096 SQLITE_HAS_CODEC SQLCIPHER_CRYPTO_CC USE_PREAD=1 SQLITE_TEMP_STORE=2 SQLCIPHER_PREPROCESSED HAVE_USLEEP HAVE_UTIME SQLITE_MALLOC_SOFT_LIMIT=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_ENABLE_COLUMN_METADATA SQLITE_DEFAULT_WAL_SYNCHRONOUS=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED SQLITE_OMIT_PROGRESS_CALLBACK SQLITE_OMIT_SHARED_CACHE OMIT_MEMLOCK SQLITE_ENABLE_FTS3_TOKENIZER SQLITE_ENABLE_DBSTAT_VTAB SQLITE_WCDB_CHECKPOINT_HANDLER SQLITE_MMAP_READWRITE SQLITE_WCDB_API_NO_HIDDEN SQLITE_ENABLE_FTS5 SQLITE_WCDB_DIRTY_PAGE_COUNT SQLITE_PRINT_BUF_SIZE=256 SQLITE_MAX_ATTACHED=64 SQLITE_USE_ALLOCA SQLITE_WCDB_SIGNAL_RETRY -GCC_WARN_64_TO_32_BIT_CONVERSION = NO -GCC_WARN_UNUSED_FUNCTION = NO -GCC_WARN_UNUSED_VARIABLE = NO -OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "Security" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/WCDBOptimizedSQLCipher -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/WCDB.swift/LICENSE b/Example/Pods/WCDB.swift/LICENSE deleted file mode 100644 index 6327a273..00000000 --- a/Example/Pods/WCDB.swift/LICENSE +++ /dev/null @@ -1,415 +0,0 @@ -Tencent is pleased to support the open source community by making WCDB available.  - -Copyright (C) 2017 THL A29 Limited, a Tencent company.  All rights reserved. -If you have downloaded a copy of the WCDB binary from Tencent, please note that -the WCDB binary is licensed under the BSD 3-Clause License. - -If you have downloaded a copy of the WCDB source code from Tencent, please note -that WCDB source code is licensed under the BSD 3-Clause License, except for -the third-party components listed below which are subject to different license -terms.  Your integration of WCDB into your own projects may require compliance -with the BSD 3-Clause License, as well as the other licenses applicable to the -third-party components included within WCDB. - -A copy of the BSD 3-Clause License is included in this file. -Other dependencies and licenses: -  -Open Source Software Licensed Under the Apache License, Version 2.0: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. - ----------------------------------------------------------------------------------------- -1. Android Source Code  4.3 -Copyright (C) 2006-2011 The Android Open Source Project -  -  -Terms of the Apache License, Version 2.0: ---------------------------------------------------- -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. -  -END OF TERMS AND CONDITIONS -  -APPENDIX: How to apply the Apache License to your work -To apply the Apache License to your work, attach the following boilerplate notice, with the -fields enclosed by brackets "[]" replaced with your own identifying information. (Don't -include the brackets!) The text should be enclosed in the appropriate comment syntax for -the file format. We also recommend that a file or class name and description of purpose be -included on the same "printed page" as the copyright notice for easier identification within -third-party archives. -  -Copyright [yyyy] [name of copyright owner] -  -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. -  -  -  -Open Source Software Licensed Under Public Domain: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLite  3.11.0 -  -  -  -Open Source Software Licensed Under the OpenSSL License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. OpenSSL  1.0.2j -Copyright (c) 1998-2016 The OpenSSL Project. -All rights reserved. -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -  -  -Terms of the OpenSSL License: ---------------------------------------------------- -LICENSE ISSUES: --------------------------------------------------------------------- -  -The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the -OpenSSL License and the original SSLeay license apply to the toolkit. -See below for the actual license texts. -  -OpenSSL License: --------------------------------------------------------------------- -Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved. -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -  -1. Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -  -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. All advertising materials mentioning features or use of this software must -display the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit. (http://www.openssl.org/)" -  -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or -promote products derived from this software without prior written permission. For -written permission, please contact openssl-core@openssl.org. -  -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" -appear in their names without prior written permission of the OpenSSL Project. -  -6. Redistributions of any form whatsoever must retain the following acknowledgment: -"This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/)" -  -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED 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 OpenSSL PROJECT OR ITS 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. -==================================================================== -* This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).  -This product includes software written by Tim Hudson (tjh@cryptsoft.com). -  -  -Original SSLeay License: --------------------------------------------------------------------- -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. -  -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). -The implementation was written so as to conform with Netscapes SSL. -  -This library is free for commercial and non-commercial use as long as the following -conditions are aheared to. The following conditions apply to all code found in this -distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. -The SSL documentation included with this distribution is covered by the same copyright -terms except that the holder is Tim Hudson (tjh@cryptsoft.com). -  -Copyright remains Eric Young's, and as such any Copyright notices in the code are not -to be removed.  If this package is used in a product, Eric Young should be given -attribution as the author of the parts of the library used. This can be in the form -of a textual message at program startup or in documentation (online or textual) -provided with the package. -  -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the copyright notice, this list of -conditions and the following disclaimer. - -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. All advertising materials mentioning features or use of this software must display -the following acknowledgement:" This product includes cryptographic software written -by Eric Young (eay@cryptsoft.com)" The word 'cryptographic' can be left out if the -rouines from the library being used are not cryptographic related :-). - -4. If you include any Windows specific code (or a derivative thereof) from the apps -directory (application code) you must include an acknowledgement: "This product includes -software written by Tim Hudson (tjh@cryptsoft.com)" -  -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. -  -The licence and distribution terms for any publically available version or derivative of -this code cannot be changed.  i.e. this code cannot simply be copied and put under another -distribution licence [including the GNU Public Licence.] -  -  -  -Open Source Software Licensed Under the ICU License: ----------------------------------------------------------------------------------------- -1. ICU4C  50.1 -Copyright (c) 1995-2012 International Business Machines Corporation and others -All rights reserved. -  -  -Terms of the ICU License: --------------------------------------------------------------------- -ICU License - ICU 1.8.1 and later -  -COPYRIGHT AND PERMISSION NOTICE -  -Copyright (c) 1995-2012 International Business Machines Corporation and others -  -All rights reserved. -  -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, provided that the above copyright -notice(s) and this permission notice appear in all copies of the Software and that both -the above copyright notice(s) and this permission notice appear in supporting -documentation. -  -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER -OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR -CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -  -Except as contained in this notice, the name of a copyright holder shall not be used in -advertising or otherwise to promote the sale, use or other dealings in this Software -without prior written authorization of the copyright holder. -  -All trademarks and registered trademarks mentioned herein are the property of their -respective owners. -  -  -Open Source Software Licensed Under the BSD 3-Clause License: -The below software in this distribution may have been modified by THL A29 Limited -(“Tencent Modifications”). -All Tencent Modifications are Copyright (C) 2017 THL A29 Limited. ----------------------------------------------------------------------------------------- -1. SQLCipher  3.4.0 -Copyright (c) 2008, ZETETIC LLC -All rights reserved. -  -  -  -Terms of the BSD 3-Clause License: --------------------------------------------------------------------- -  -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -l  Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -l  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. - -l  Neither the name of [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. diff --git a/Example/Pods/WCDB.swift/README.md b/Example/Pods/WCDB.swift/README.md deleted file mode 100644 index e52a21c4..00000000 --- a/Example/Pods/WCDB.swift/README.md +++ /dev/null @@ -1,287 +0,0 @@ -# WCDB - -[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/wcdb/pulls) -[![Release Version](https://img.shields.io/badge/release-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/releases) -[![WeChat Approved iOS](https://img.shields.io/badge/Wechat_Approved_iOS-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/blob/master/README.md#wcdb-for-iosmacos) -[![WeChat Approved Android](https://img.shields.io/badge/Wechat_Approved_Android-1.0.5-brightgreen.svg)](https://github.com/Tencent/wcdb/blob/master/README.md#wcdb-for-android) -[![Platform](https://img.shields.io/badge/Platform-%20iOS%20%7C%20macOS%20%7C%20Android-brightgreen.svg)](https://github.com/Tencent/wcdb/wiki) - -中文版本请参看[这里][wcdb-wiki] - -WCDB is an **efficient**, **complete**, **easy-to-use** mobile database framework used in the WeChat application. It's currently available on iOS, macOS and Android. - -# WCDB for iOS/macOS - -## Features - -* **Easy-to-use**. Through WCDB, you can get objects from database in one line code. - - * **WINQ** (WCDB language integrated query): WINQ is a native data querying capability which frees developers from writing glue code to concatenate SQL query strings. - - * **ORM** (Object Relational Mapping): WCDB provides a flexible, easy-to-use ORM for creating tables, indices and constraints, as well as CRUD through ObjC objects. - - ```objective-c - [database getObjectsOfClass:WCTSampleConvenient.class - fromTable:tableName - where:WCTSampleConvenient.intValue>=10 - limit:20]; - ``` - -* **Efficient**. Through the framework layer and sqlcipher source optimization, WCDB have more efficient performance. - - * **Multi-threaded concurrency**: WCDB supports concurrent read-read and read-write access via connection pooling. - * **Batch Write Performance Test**. - ![](https://raw.githubusercontent.com/wiki/Tencent/wcdb/assets/benchmark/baseline_batch_write.png) - For more benchmark data, please refer to [our benchmark][Benchmark-iOS]. - -* **Complete**. - - * **Encryption Support**: WCDB supports database encryption via [SQLCipher][sqlcipher]. - * **Corruption recovery**: WCDB provides a built-in repair kit for database corruption recovery. - * **Anti-injection**: WCDB provides a built-in protection from SQL injection. - -## Getting Started - -### Prerequisites - -* Apps using WCDB can target: iOS 7 or later, macOS 10.9 or later. -* Xcode 8.0 or later required. -* Objective-C++ required. - -### Installation - -* **Via Cocoapods:** - 1. Install [CocoaPods.](https://guides.cocoapods.org/using/getting-started.html) - 2. Run `pod repo update` to make CocoaPods aware of the latest available WCDB versions. - 3. In your Podfile, add `pod 'WCDB'` to your app target. - 4. From the command line, run `pod install`. - 5. Use the `.xcworkspace` file generated by CocoaPods to work on your project. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Carthage:** - 1. Install [Carthage][install-carthage]. - 2. Add `github "Tencent/WCDB"` to your Cartfile. - 3. Run `carthage update`. - 4. Drag `WCDB.framework` from the appropriate platform directory in `Carthage/Build/` to the `Linked Binary and Libraries` section of your Xcode project’s `Build Phases` settings. - 5. On your application targets' `Build Phases` settings tab, click the "+" icon and choose `New Run Script Phase`. Create a Run Script with `carthage copy-frameworks` and add the paths to the frameworks under `Input Files`: `$(SRCROOT)/Carthage/Build/iOS/WCDB.framework` or `$(SRCROOT)/Carthage/Build/Mac/WCDB.framework`. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Dynamic Framework**: - **Note that Dynamic frameworks are not compatible with iOS 7. See “Static Framework” for iOS 7 support.** - 1. Getting source code from git repository and update the submodule of sqlcipher. - - `git clone https://github.com/Tencent/wcdb.git` - - `cd wcdb` - - `git submodule update --init sqlcipher ` - 2. Drag `WCDB.xcodeproj` in `wcdb/apple/` into your project. - 3. Add `WCDB.framework` to the `Enbedded Binaries` section of your Xcode project's `General settings`. **Note that there are two frameworks here and the dynamic one should be chosen. You can check it at `Build Phases`->`Target Dependencies`. The right one is `WCDB` while `WCDB iOS Static is used for static lib.** - 4. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 5. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** -* **Via Static Framework:** - 1. Getting source code from git repository and update the submodule of sqlcipher. - - `git clone https://github.com/Tencent/wcdb.git` - - `cd wcdb` - - `git submodule update --init sqlcipher ` - 2. Drag `WCDB.xcodeproj` in `wcdb/apple/` into your project. - 3. Add `WCDB iOS Static` to the `Target Dependencies` section of your Xcode project's `Build Phases` settings. - 4. Add `WCDB.framework`, `libz.tbd` to the `Linked Binary and Libraries` section of your Xcode project's `Build Phases` settings. Note that there are two `WCDB.framework`, you should choose the one from `WCDB iOS Static` target. - 5. Add `-all_load` and `-ObjC` to the `Other Linker Flags` section of your Xcode project's `Build Settings`. - 6. Add `#import ` at the top of your Objective-C++ source files and start your WCDB journey. - 7. **Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension `.m` to `.mm`.** - -## Tutorials - -Tutorials can be found [here][iOS-tutorial]. - -## Documentations - -* Documentations can be found on [our Wiki][wcdb-wiki]. -* API references for iOS/macOS can be found [here][wcdb-docs-ios]. -* Performance data can be found on [our benchmark][Benchmark-iOS]. - -# WCDB for Android - -## Features - -* Database encryption via [SQLCipher][sqlcipher]. -* ORM/persistence solution via [Room][room] from Android Architecture Components. -* Concurrent access via connection pooling from modern Android framework. -* Repair toolkit for database corruption recovery. -* Database backup and recovery utility optimized for small backup size. -* Log redirection and various tracing facilities. -* API 14 (Android 4.0) and above are supported. - -## Getting Started - -To include WCDB to your project, choose either way: import via Maven or via AAR package. - -### Import via Maven - -To import WCDB via Maven repositories, add the following lines to `build.gradle` on your -app module: - -```gradle -dependencies { - compile 'com.tencent.wcdb:wcdb-android:1.0.8' - // Replace "1.0.8" to any available version. -} -``` - -This will cause Gradle to download AAR package from JCenter while building your application. - -If you want to use Room persistence library, you need to add the Google Maven repository to -`build.gradle` to your **root project**. - -```gradle -allprojects { - repositories { - jcenter() - google() // Add this line - } -} -``` - -Also add dependencies to module `build.gradle`. - -```gradle -dependencies { - compile 'com.tencent.wcdb:room:1.0.8' - // Replace "1.0.8" to any available version. - - annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' - // Don't forget to include Room annotation compiler from Google. -} -``` - -### Import Prebuilt AAR Package - -   1. **Download AAR package from release page.** -   2. **Import the AAR as new module.** In Android Studio, select `File -> New -> New Module...` menu and choose `"Import JAR/AAR Package"`. -   3. **Add a dependency on the new module.** This can be done using `File -> Project Structure...` in Android Studio, or by adding following code to application's `build.gradle`: -```gradle -dependencies { - // Change "wcdb" to the actual module name specified in step 2. - compile project(':wcdb') -} -``` - -### Migrate from Plain-text SQLite Databases - -WCDB has interfaces very similar to Android SQLite Database APIs. To migrate you application from -AOSP API, change import path from `android.database.*` to `com.tencent.wcdb.*`, and -`android.database.sqlite.*` to `com.tencent.wcdb.database.*`. After import path update, -your application links to WCDB instead of AOSP API. - -To open or create an encrypted database, use with-password versions of -`SQLiteDatabase.openOrCreateDatabase()`, `SQLiteOpenHelper.getWritableDatabase()`, -or `Context.openOrCreateDatabase()`. - -*Note: WCDB uses `byte[]` for password instead of `String` in SQLCipher Android Binding.* - -```java -String password = "MyPassword"; -SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("/path/to/database", password.getBytes(), - null, null); -``` - -See `sample-encryptdb` for sample for transferring data between plain-text and encrypted -databases. - -### Use WCDB with Room - -To use WCDB with Room library, follow the [Room instructions][room]. The only code to change -is specifying `WCDBOpenHelperFactory` when getting instance of the database. - -```java -SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec() - .setPageSize(4096) - .setKDFIteration(64000); - -WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory() - .passphrase("passphrase".getBytes()) // passphrase to the database, remove this line for plain-text - .cipherSpec(cipherSpec) // cipher to use, remove for default settings - .writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed - .asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed - -AppDatabase db = Room.databaseBuilder(this, AppDatabase.class, "app-db") - .allowMainThreadQueries() - .openHelperFactory(factory) // specify WCDBOpenHelperFactory when opening database - .build(); -``` - -See `sample-persistence` for samples using Room library with WCDB. -See `sample-room-with-a-view` for samples using Room library with WCDB and other architecture components from Google. - -> `sample-room-with-a-view` comes from Google's CodeLabs with modification of just a few rows. Search for *\[WCDB\]* keyword for the modification. -> -> See [here][room-codelabs] for the original tutorial. - -### Corruption Recovery - -See `sample-repairdb` for instructions how to recover corrupted databases using `RepairKit`. - -### Redirect Log Output - -By default, WCDB prints its log message to system logcat. You may want to change this -behavior in order to, for example, save logs for troubleshooting. WCDB can redirect -all of its log outputs to user-defined routine using `Log.setLogger(LogCallback)` -method. - -## Build from Sources - -### Build WCDB Android with Prebuilt Dependencies - -WCDB itself can be built apart from its dependencies using Gradle or Android Studio. -To build WCDB Android library, run Gradle on `android` directory: - -```bash -$ cd android -$ ./gradlew build -``` - -Building WCDB requires Android NDK installed. If Gradle failed to find your SDK and/or -NDK, you may need to create a file named `local.properties` on the `android` directory -with content: - -``` -sdk.dir=path/to/sdk -ndk.dir=path/to/ndk -``` - -Android Studio will do this for you when the project is imported. - -### Build Dependencies from Sources - -WCDB depends on OpenSSL crypto library and SQLCipher. You can rebuild all dependencies -if you wish. In this case, a working C compiler on the host system, Perl 5, Tcl and a -bash environment is needed to be installed on your system. - -To build dependencies, checkout all submodules, set `ANDROID_NDK_ROOT` environment -variable to your NDK path, then run `build-depends-android.sh`: - -```bash -$ export ANDROID_NDK_ROOT=/path/to/ndk -$ ./build-depends-android.sh -``` - -This will build OpenSSL crypto library and generate SQLCipher amalgamation sources -and place them to proper locations suitable for WCDB library building. - -## Documentations - -* Documentations can be found on [our Wiki][wcdb-wiki]. -* API references for Android can be found [here][wcdb-docs-android]. - -## Contributing - -If you are interested in contributing, check out the [CONTRIBUTING.md], also join our [Tencent OpenSource Plan](https://opensource.tencent.com/contribution). - -[install-carthage]: https://github.com/Carthage/Carthage#installing-carthage -[wcdb-wiki]: https://github.com/Tencent/wcdb/wiki -[wcdb-docs-ios]: https://tencent.github.io/wcdb/references/ios/index.html -[wcdb-docs-android]: https://tencent.github.io/wcdb/references/android/index.html -[sqlcipher]: https://github.com/sqlcipher/sqlcipher -[room]: https://developer.android.com/topic/libraries/architecture/room -[room-codelabs]: https://codelabs.developers.google.com/codelabs/android-room-with-a-view -[iOS-tutorial]: https://github.com/Tencent/wcdb/wiki/iOS-macOS-Tutorial -[Benchmark-iOS]: https://github.com/Tencent/wcdb/wiki/WCDB-iOS-benchmark - diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Column.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Column.swift deleted file mode 100644 index a759a3d4..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Column.swift +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct Column: Describable { - public private(set) var description: String - - public static let all: Column = Column(named: "*") - public static let rowid: Column = Column(named: "rowid") - - public init(named name: String) { - description = name - } - - public func `in`(table: String) -> Column { - return Column(named: "\(table).\(description)") - } -} - -extension Column: ColumnConvertible, ExpressionOperable { - public func asColumn() -> Column { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnDef.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ColumnDef.swift deleted file mode 100644 index db6aaba6..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnDef.swift +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class ColumnDef: Describable { - public private(set) var description: String - - public init(with columnConvertible: ColumnConvertible, and optionalType: ColumnType? = nil) { - description = columnConvertible.asColumn().description - if let type = optionalType { - description.append(" \(type.description)") - } - } - - @discardableResult - public func makePrimary(orderBy term: OrderTerm? = nil, - isAutoIncrement: Bool = false, - onConflict conflict: Conflict? = nil) -> ColumnDef { - description.append(" PRIMARY KEY") - if term != nil { - description.append(" \(term!.description)") - } - if isAutoIncrement { - description.append(" AUTOINCREMENT") - } - if conflict != nil { - description.append(" ON CONFLICT \(conflict!.description)") - } - return self - } - - public enum DefaultType: Describable { - case null - case int32(Int32) - case int64(Int64) - case bool(Bool) - case text(String) - case float(Double) - case BLOB(Data) - case expression(Expression) - case currentTime - case currentDate - case currentTimestamp - - public var description: String { - switch self { - case .null: - return "NULL" - case .int32(let value): - return LiteralValue(value).description - case .int64(let value): - return LiteralValue(value).description - case .bool(let value): - return LiteralValue(value).description - case .text(let value): - return LiteralValue(value).description - case .float(let value): - return LiteralValue(value).description - case .BLOB(let value): - return LiteralValue(value).description - case .expression(let value): - return value.description - case .currentDate: - return "CURRENT_DATE" - case .currentTime: - return "CURRENT_TIME" - case .currentTimestamp: - return "CURRENT_TIMESTAMP" - } - } - } - - @discardableResult - public func makeDefault(to defaultValue: DefaultType) -> ColumnDef { - description.append(" DEFAULT \(defaultValue.description)") - return self - } - - @discardableResult - public func makeNotNull() -> ColumnDef { - description.append(" NOT NULL") - return self - } - - @discardableResult - public func makeUnique() -> ColumnDef { - description.append(" UNIQUE") - return self - } - - @discardableResult - public func makeForeignKey(_ foreignKey: ForeignKey) -> ColumnDef { - description.append(" \(foreignKey.description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnIndex.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ColumnIndex.swift deleted file mode 100644 index cdeaf252..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnIndex.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct ColumnIndex: Describable { - public private(set) var description: String - - public init(with columnConvertible: ColumnConvertible, orderBy term: OrderTerm? = nil) { - description = columnConvertible.asColumn().description - if let wrappedTerm = term { - description.append(" \(wrappedTerm.description)") - } - } - - public init(with expressionConvertible: ExpressionConvertible, orderBy term: OrderTerm? = nil) { - description = expressionConvertible.asExpression().description - if let wrappedTerm = term { - description.append(" \(wrappedTerm.description)") - } - } -} - -extension ColumnIndex: ColumnIndexConvertible { - public func asIndex() -> ColumnIndex { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnResult.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ColumnResult.swift deleted file mode 100644 index 753f5cb7..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnResult.swift +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class ColumnResult: Describable { - public private(set) var description: String - - public init(with expressionConvertible: ExpressionConvertible) { - description = expressionConvertible.asExpression().description - } - - @discardableResult - public func `as`(_ alias: String) -> ColumnResult { - description.append(" AS " + alias) - return self - } -} - -extension ColumnResult: ColumnResultConvertible { - public func asColumnResult() -> ColumnResult { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnType.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ColumnType.swift deleted file mode 100644 index c9c7a22a..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ColumnType.swift +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public enum ColumnType: Describable { - case integer32 - case integer64 - case text - case float - case BLOB - case null - - public var description: String { - switch self { - case .integer32: - fallthrough - case .integer64: - return "INTEGER" - case .float: - return "REAL" - case .text: - return "TEXT" - case .BLOB: - return "BLOB" - case .null: - return "NULL" - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Conflict.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Conflict.swift deleted file mode 100644 index 9ea92665..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Conflict.swift +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public enum Conflict: Describable { - case rollback - case abort - case fail - case ignore - case replace - - public var description: String { - switch self { - case .rollback: - return "ROLLBACK" - case .abort: - return "ABORT" - case .fail: - return "FAIL" - case .ignore: - return "IGNORE" - case .replace: - return "REPLACE" - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Convertible.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Convertible.swift deleted file mode 100644 index 0a03d478..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Convertible.swift +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol OrderConvertible { - func asOrder() -> Order -} - -public protocol SpecificOrderConvertible: OrderConvertible { - func asOrder(by term: OrderTerm?) -> Order -} - -extension SpecificOrderConvertible { - public func asOrder() -> Order { - return asOrder(by: nil) - } -} - -public protocol SpecificColumnDefConvertible { - func asDef(with columnType: ColumnType?) -> ColumnDef -} - -public protocol ColumnIndexConvertible { - func asIndex() -> ColumnIndex -} - -public protocol SpecificColumnIndexConvertible: ColumnIndexConvertible { - func asIndex(orderBy term: OrderTerm?) -> ColumnIndex -} - -extension SpecificColumnIndexConvertible { - public func asIndex() -> ColumnIndex { - return asIndex(orderBy: nil) - } -} - -public protocol ColumnResultConvertible { - func asColumnResult() -> ColumnResult -} - -public protocol TableOrSubqueryConvertible { - func asTableOrSubquery() -> Subquery -} - -public protocol ExpressionConvertible: ColumnResultConvertible, SpecificOrderConvertible { - func asExpression() -> Expression -} - -extension ExpressionConvertible { - public func asColumnResult() -> ColumnResult { - return ColumnResult(with: asExpression()) - } - public func asOrder(by term: OrderTerm?) -> Order { - return Order(with: asExpression(), by: term) - } -} - -public protocol ColumnConvertible: ExpressionConvertible, SpecificColumnIndexConvertible, SpecificColumnDefConvertible { - func asColumn() -> Column - func `in`(table: String) -> Column -} - -extension ColumnConvertible { - public func asExpression() -> Expression { - return Expression(with: self) - } - - public func asIndex(orderBy term: OrderTerm?) -> ColumnIndex { - return ColumnIndex(with: self, orderBy: term) - } - - public func asDef(with columnType: ColumnType? = nil) -> ColumnDef { - return ColumnDef(with: self, and: columnType) - } - - public func `in`(table: String) -> Column { - return asColumn().in(table: table) - } -} - -public protocol LiteralValueConvertible: ExpressionConvertible { - func asLiteralValue() -> LiteralValue -} - -extension LiteralValueConvertible { - public func asExpression() -> Expression { - return Expression(with: self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Describable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Describable.swift deleted file mode 100644 index 20a44994..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Describable.swift +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -//TODO: Refactor: change all winq classes into structs -public typealias Describable = CustomStringConvertible diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Expression.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Expression.swift deleted file mode 100644 index a9968ebd..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Expression.swift +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct Expression: Describable { - public private(set) var description: String - - public static let bindParameter = Expression(withRaw: "?") - - public init(with columnConvertible: ColumnConvertible) { - description = columnConvertible.asColumn().description - } - - public init(with literalValueConvertible: LiteralValueConvertible) { - description = literalValueConvertible.asLiteralValue().description - } - - public init(with statementSelect: StatementSelect) { - description = statementSelect.description - } - - init(withRaw raw: String) { - description = raw - } -} - -extension Expression: ExpressibleByNilLiteral { - public init(nilLiteral value: ()) { - self.init(with: LiteralValue(value)) - } -} -extension Expression: ExpressibleByBooleanLiteral { - public init(booleanLiteral value: Bool) { - self.init(with: LiteralValue(value)) - } -} -extension Expression: ExpressibleByIntegerLiteral { - public init(integerLiteral value: Int) { - self.init(with: LiteralValue(value)) - } -} -extension Expression: ExpressibleByFloatLiteral { - public init(floatLiteral value: Double) { - self.init(with: LiteralValue(value)) - } -} -extension Expression: ExpressibleByStringLiteral { - public init(stringLiteral value: String) { - self.init(with: LiteralValue(value)) - } -} - -extension Expression: ExpressionOperable { - public static func exists(_ statementSelect: StatementSelect) -> Expression { - return Expression.operate(prefix: "EXISTS ", operand: statementSelect) - } - public static func notExists(_ statementSelect: StatementSelect) -> Expression { - return Expression.operate(prefix: "NOT EXISTS ", operand: statementSelect) - } - - public static func combine(_ expressionConvertibleList: ExpressionConvertible...) -> Expression { - return combine(expressionConvertibleList) - } - public static func combine(_ expressionConvertibleList: [ExpressionConvertible]) -> Expression { - return Expression(withRaw: "(\(expressionConvertibleList.joined()))") - } - - //Function - public static func function(named name: String, - _ expressions: ExpressionConvertible..., - isDistinct: Bool = false) -> Expression { - return function(named: name, expressions, isDistinct: isDistinct) - } - public static func function(named name: String, - _ expressions: [ExpressionConvertible], - isDistinct: Bool = false) -> Expression { - return Expression.operate(title: name, infix: isDistinct ? "DISTINCT" : nil, operands: expressions) - } - - public static func `case`(_ expressionConvertible: ExpressionConvertible, - _ flows: (when: ExpressionConvertible, then: ExpressionConvertible)..., - `else`: ExpressionConvertible) -> Expression { - return `case`(expressionConvertible.asExpression(), flows, else: `else`.asExpression()) - } - public static func `case`(_ `case`: ExpressionConvertible, - _ flows: [(when: ExpressionConvertible, then: ExpressionConvertible)], - `else`: ExpressionConvertible) -> Expression { - var descrption = "CASE \(`case`.asExpression().description) " - descrption.append(flows.joined({ "WHEN \($0.when) THEN \($0.then) " })) - descrption.append("ELSE \(`else`.asExpression().description) END") - return Expression(withRaw: descrption) - } - - public func asExpression() -> Expression { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ForeignKey.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ForeignKey.swift deleted file mode 100644 index 07c044f5..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ForeignKey.swift +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class ForeignKey: Describable { - public private(set) var description: String - - public init(withForeignTable table: String, and columnConvertibleList: [ColumnConvertible]) { - description = "REFERENCES \(table)" - if !columnConvertibleList.isEmpty { - description.append("(\(columnConvertibleList.joined(separateBy: ", ")))") - } - } - - public convenience init(withForeignTable table: String, and columnConvertibleList: ColumnConvertible...) { - self.init(withForeignTable: table, and: columnConvertibleList) - } - - public enum Action: Describable { - case setNull - case setDefault - case cascade - case restrict - case noAction - - public var description: String { - switch self { - case .setNull: - return "SET NULL" - case .setDefault: - return "SET DEFAULT" - case .cascade: - return "CASCADE" - case .restrict: - return "RESTRICT" - case .noAction: - return "NO ACTION" - } - } - } - - @discardableResult - public func onDelete(_ action: Action) -> ForeignKey { - description.append(" ON DELETE \(action.description)") - return self - } - - @discardableResult - public func onUpdate(_ action: Action) -> ForeignKey { - description.append(" ON UPDATE \(action.description)") - return self - } - - @discardableResult - public func match(name: String) -> ForeignKey { - description.append(" MATCH \(name)") - return self - } - - public enum Deferrable: Describable { - case deferred - case immediate - - public var description: String { - switch self { - case .deferred: - return "INITIALLY DEFERRED" - case .immediate: - return "INITIALLY IMMEDIATE" - } - } - } - - @discardableResult - public func deferrable(_ deferrable: Deferrable) -> ForeignKey { - description.append(" DEFERRABLE \(deferrable.description)") - return self - } - - @discardableResult - public func notDeferrable(_ deferrable: Deferrable) -> ForeignKey { - description.append(" NOT DEFERRABLE \(deferrable.description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/FundamentalValue.swift b/Example/Pods/WCDB.swift/swift/source/abstract/FundamentalValue.swift deleted file mode 100644 index 39399325..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/FundamentalValue.swift +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -// nullable, Int32, Int64, Double, String, Data -public struct FundamentalValue { - private let base: Any? - public let type: ColumnType - - public init(_ _: Void? = nil) { - base = nil - type = .null - } - - public init(_ value: Int32) { - base = value - type = .integer32 - } - - public init(_ value: Int64) { - base = value - type = .integer64 - } - - public init(_ value: Double) { - base = value - type = .float - } - - public init(_ value: String) { - base = value - type = .text - } - - public init(_ value: Data) { - base = value - type = .BLOB - } - - public init(_ encodedValue: T) { - self = encodedValue.archivedValue() - } - - public var int32Value: Int32 { - switch type { - case .integer32: - return base as! Int32 - case .integer64: - return Int32(truncatingIfNeeded: base as! Int64) - case .float: - return Int32(base as! Double) - case .text: - return Int32(base as! String) ?? 0 - default: - return 0 - } - } - - public var int64Value: Int64 { - switch type { - case .integer32: - return Int64(base as! Int32) - case .integer64: - return base as! Int64 - case .float: - return Int64(base as! Double) - case .text: - return Int64(base as! String) ?? 0 - default: - return 0 - } - } - - public var stringValue: String { - switch type { - case .integer32: - return "\(base as! Int32)" - case .integer64: - return "\(base as! Int64)" - case .float: - return "\(base as! Double)" - case .text: - return base as! String - case .BLOB: - return String(data: base as! Data, encoding: .utf8) ?? "" - default: - return "" - } - } - - public var doubleValue: Double { - switch type { - case .integer32: - return Double(base as! Int32) - case .integer64: - return Double(base as! Int64) - case .float: - return base as! Double - case .text: - return Double(base as! String) ?? 0 - default: - return 0 - } - } - - public var dataValue: Data { - switch type { - case .integer32: - fallthrough - case .integer64: - fallthrough - case .float: - fallthrough - case .text: - return stringValue.data(using: .utf8) ?? Data() - case .BLOB: - return (base as? Data) ?? Data() - default: - return Data() - } - } -} - -public typealias FundamentalColumn = [FundamentalValue] -public typealias FundamentalRow = [FundamentalValue] - -public typealias FundamentalRowXColumn = [FundamentalRow] - -extension Array where Element==[FundamentalValue] { - public subscript(row row: Array.Index, column column: Array.Index) -> FundamentalValue { - return self[row][column] - } - - public subscript(row row: Array.Index) -> FundamentalColumn { - return self[row] - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Handle.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Handle.swift deleted file mode 100644 index 03eba8cf..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Handle.swift +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public typealias Tag = Int - -public final class Handle { - private var handle: SQLite3? - - public let path: String - public internal(set) var tag: Tag? = nil { - didSet { - tracer?.userInfo = tag - } - } - - typealias CommittedHook = (Handle, Int, Void?) -> Void - private struct CommittedHookInfo { - var onCommitted: CommittedHook - weak var handle: Handle? - } - private var committedHookInfo: CommittedHookInfo? - - private var tracer: Tracer? - - init(withPath path: String) { - DispatchQueue.once(name: "com.tencent.wcdb.handle") { - sqlite3_config_multithread() - sqlite3_config_memstatus(Int32(truncating: false)) - sqlite3_config_log({ (_, code, message) in - let msg = (message != nil) ? String(cString: message!) : "" - Error.reportSQLiteGlobal(code: Int(code), message: msg) - }, nil) - } - self.path = path - } - - deinit { - try? close() - } - - func open() throws { - let directory = URL(fileURLWithPath: path).deletingLastPathComponent().path - try File.createDirectoryWithIntermediateDirectories(atPath: directory) - let rc = sqlite3_open(path, &handle) - guard rc == SQLITE_OK else { - throw Error.reportSQLite(tag: tag, - path: path, - operation: .open, - code: rc, - message: String(cString: sqlite3_errmsg(handle)) - ) - } - } - - func close() throws { - let rc = sqlite3_close(handle) - guard rc == SQLITE_OK else { - throw Error.reportSQLite(tag: tag, - path: path, - operation: .close, - code: rc, - message: String(cString: sqlite3_errmsg(handle)) - ) - } - handle = nil - } - - public func prepare(_ statement: Statement) throws -> HandleStatement { - assert(statement.statementType != .transaction, "[prepare] a transaction is not allowed, use [exec] instead") - var stmt: OpaquePointer? = nil - let rc = sqlite3_prepare_v2(handle, statement.description, -1, &stmt, nil) - guard rc==SQLITE_OK else { - throw Error.reportSQLite(tag: tag, - path: path, - operation: .prepare, - extendedError: sqlite3_extended_errcode(handle), - sql: statement.description, - code: rc, - message: String(cString: sqlite3_errmsg(handle)) - ) - } - return HandleStatement(with: stmt!, and: self) - } - - public func exec(_ statement: Statement) throws { - let rc = sqlite3_exec(handle, statement.description, nil, nil, nil) - let result = rc == SQLITE_OK - if let tracer = self.tracer { - if statement.statementType == .transaction, - let statementTransaction = statement as? StatementTransaction, - let transactionType = statementTransaction.transactionType { - switch transactionType { - case .begin: - if result { - tracer.shouldAggregation = true - } - case .commit: - if result { - tracer.shouldAggregation = false - } - case .rollback: - tracer.shouldAggregation = false - } - } - } - guard result else { - throw Error.reportSQLite(tag: tag, - path: path, - operation: .exec, - extendedError: sqlite3_extended_errcode(handle), - sql: statement.description, - code: rc, - message: String(cString: sqlite3_errmsg(handle)) - ) - } - } - - public var changes: Int { - return Int(sqlite3_changes(handle)) - } - - public var isReadonly: Bool { - return sqlite3_db_readonly(handle, nil)==1 - } -} - -//Cipher -extension Handle { - public func setCipher(key: Data) throws { - let rc = key.withUnsafeBytes ({ (bytes: UnsafeRawBufferPointer) -> Int32 in - return sqlite3_key(handle, bytes.baseAddress, Int32(key.count)) - }) - guard rc == SQLITE_OK else { - throw Error.reportSQLite(tag: tag, - path: path, - operation: .setCipherKey, - extendedError: sqlite3_extended_errcode(handle), - code: rc, - message: String(cString: sqlite3_errmsg(handle)) - ) - } - } -} - -//Repair -extension Handle { - public static let backupSubfix = "-backup" - - public var backupPath: String { - return path+Handle.backupSubfix - } - - public func backup(withKey optionalKey: Data? = nil) throws { - var rc = SQLITE_OK - if let key = optionalKey { - key.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) -> Void in - rc = sqliterk_save_master(handle, backupPath, bytes.baseAddress, Int32(key.count)) - } - } else { - rc = sqliterk_save_master(handle, backupPath, nil, 0) - } - guard rc == SQLITERK_OK else { - throw Error.reportRepair(path: path, - operation: .saveMaster, - code: Int(rc)) - } - } - - public func recover(fromPath source: String, - withPageSize pageSize: Int32, - databaseKey optionalDatabaseKey: Data? = nil, - backupKey optionalBackupKey: Data? = nil) throws { - var rc = SQLITERK_OK - - let backupPath = source+Handle.backupSubfix - - let kdfSalt = UnsafeMutablePointer.allocate(capacity: 16) - memset(kdfSalt, 0, 16) - - var info: OpaquePointer? = nil - let backupSize: Int32 = Int32(optionalBackupKey?.count ?? 0) - if let backupKey = optionalBackupKey { - backupKey.withUnsafeBytes({ (bytes: UnsafeRawBufferPointer) -> Void in - rc = sqliterk_load_master(backupPath, bytes.baseAddress, backupSize, nil, 0, &info, kdfSalt) - }) - }else { - rc = sqliterk_load_master(backupPath, nil, backupSize, nil, 0, &info, kdfSalt) - } - - guard rc == SQLITERK_OK else { - throw Error.reportRepair(path: backupPath, - operation: .repair, - code: Int(rc)) - } - - var conf = sqliterk_cipher_conf() - conf.page_size = pageSize - conf.kdf_salt = UnsafePointer(kdfSalt) - conf.use_hmac = 1 - - typealias RepairKit = OpaquePointer - var rk: RepairKit? = nil - - let databaseSize: Int32 = Int32(optionalDatabaseKey?.count ?? 0) - if let databaseKey = optionalDatabaseKey { - databaseKey.withUnsafeBytes({ (bytes: UnsafeRawBufferPointer) -> Void in - sqliterk_cipher_conf_set_key(&conf, bytes.baseAddress, databaseSize) - rc = sqliterk_open(source, &conf, &rk) - }) - }else { - sqliterk_cipher_conf_set_key(&conf, nil, 0) - rc = sqliterk_open(source, &conf, &rk) - } - guard rc == SQLITERK_OK else { - throw Error.reportRepair(path: source, - operation: .repair, - code: Int(rc)) - } - - rc = sqliterk_output(rk, handle, info, UInt32(SQLITERK_OUTPUT_ALL_TABLES)) - guard rc == SQLITERK_OK else { - throw Error.reportRepair(path: source, - operation: .repair, - code: Int(rc)) - } - } -} - -extension Handle { - public static let subfixs: [String] = ["", "-wal", "-journal", "-shm", Handle.backupSubfix] -} - -extension Handle { - public typealias SQLTracer = (String) -> Void - - func lazyTracer() -> Tracer? { - if tracer == nil && handle != nil { - tracer = Tracer(with: handle!) - } - return tracer - } - - func trace(sql sqlTracer: @escaping SQLTracer) { - lazyTracer()?.trace(sql: sqlTracer) - } - - public typealias PerformanceTracer = (Tag?, [String: Int], Int64) -> Void // Tag?, (SQL, count), cost - - func trace(performance performanceTracer: @escaping PerformanceTracer) { - lazyTracer()?.track(performance: { (sqls, cost, userInfo) in - performanceTracer(userInfo as? Tag, sqls, cost) - }) - } -} - -//Commit hook -extension Handle { - func register(onCommitted: @escaping CommittedHook) { - committedHookInfo = CommittedHookInfo(onCommitted: onCommitted, handle: self) - sqlite3_wal_hook(handle, { (pointer, _, _, pages) -> Int32 in - let committedHookInfo = pointer!.assumingMemoryBound(to: CommittedHookInfo.self).pointee - committedHookInfo.onCommitted(committedHookInfo.handle!, Int(pages), nil) - return SQLITE_OK - }, &committedHookInfo) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/HandleStatement.swift b/Example/Pods/WCDB.swift/swift/source/abstract/HandleStatement.swift deleted file mode 100644 index f34888d6..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/HandleStatement.swift +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class HandleStatement { - private var stmt: SQLite3Statement? - - private let handle: Handle - - public var path: String { - return handle.path - } - - public var tag: Tag? { - return handle.tag - } - - init(with stmt: SQLite3Statement, and handle: Handle) { - self.stmt = stmt - self.handle = handle - } - - deinit { - try? finalize() - } - - @discardableResult - public func step() throws -> Bool { - let rc = sqlite3_step(stmt) - guard rc==SQLITE_OK || rc==SQLITE_DONE || rc==SQLITE_ROW else { - let dbHandle = sqlite3_db_handle(stmt) - throw Error.reportSQLite(tag: handle.tag, - path: handle.path, - operation: .step, - extendedError: sqlite3_extended_errcode(dbHandle), - sql: String(cString: sqlite3_sql(stmt)), - code: rc, - message: String(cString: sqlite3_errmsg(dbHandle)) - ) - } - return rc==SQLITE_ROW - } - - public func reset() throws { - let rc = sqlite3_reset(stmt) - guard rc==SQLITE_OK else { - let dbHandle = sqlite3_db_handle(stmt) - throw Error.reportSQLite(tag: handle.tag, - path: handle.path, - operation: .finalize, - extendedError: sqlite3_extended_errcode(dbHandle), - code: rc, - message: String(cString: sqlite3_errmsg(dbHandle)) - ) - } - } - - public var changes: Int { - return Int(sqlite3_changes(sqlite3_db_handle(stmt))) - } - - public func bind(_ value: FundamentalValue, toIndex index: Int) { - switch value.type { - case .integer32: - sqlite3_bind_int(stmt, Int32(index), value.int32Value) - case .integer64: - sqlite3_bind_int64(stmt, Int32(index), value.int64Value) - case .float: - sqlite3_bind_double(stmt, Int32(index), value.doubleValue) - case .text: - sqlite3_bind_text_transient(stmt, Int32(index), value.stringValue, -1) - case .BLOB: - let data = value.dataValue - data.withUnsafeBytes ({ (bytes: UnsafeRawBufferPointer) -> Void in - sqlite3_bind_blob_transient(stmt, Int32(index), bytes.baseAddress, Int32(data.count)) - }) - case .null: - sqlite3_bind_null(stmt, Int32(index)) - } - } - - public func bind(_ value: Int32, toIndex index: Int) { - sqlite3_bind_int(stmt, Int32(index), value) - } - - public func bind(_ value: Int64, toIndex index: Int) { - sqlite3_bind_int64(stmt, Int32(index), value) - } - - public func bind(_ value: Double, toIndex index: Int) { - sqlite3_bind_double(stmt, Int32(index), value) - } - - public func bind(_ value: String, toIndex index: Int) { - sqlite3_bind_text_transient(stmt, Int32(index), value, -1) - } - - public func bind(_ value: Data, toIndex index: Int) { - value.withUnsafeBytes ({ (bytes: UnsafeRawBufferPointer) -> Void in - sqlite3_bind_blob_transient(stmt, Int32(index), bytes.baseAddress, Int32(value.count)) - }) - } - - public func bind(_ _: Void?, toIndex index: Int) { - sqlite3_bind_null(stmt, Int32(index)) - } - - public func columnValue(atIndex index: Int) -> FundamentalValue { - switch columnType(atIndex: index) { - case .integer32: - return FundamentalValue(columnValue(atIndex: index, of: Int32.self)) - case .integer64: - return FundamentalValue(columnValue(atIndex: index, of: Int64.self)) - case .float: - return FundamentalValue(columnValue(atIndex: index, of: Double.self)) - case .text: - return FundamentalValue(columnValue(atIndex: index, of: String.self)) - case .BLOB: - return FundamentalValue(columnValue(atIndex: index, of: Data.self)) - case .null: - return FundamentalValue(nil) - } - } - - public func columnValue(atIndex index: Int, of type: Int32.Type = Int32.self) -> Int32 { - return sqlite3_column_int(stmt, Int32(index)) - } - - public func columnValue(atIndex index: Int, of type: Int64.Type = Int64.self) -> Int64 { - return sqlite3_column_int64(stmt, Int32(index)) - } - - public func columnValue(atIndex index: Int, of type: Double.Type = Double.self) -> Double { - return sqlite3_column_double(stmt, Int32(index)) - } - - public func columnValue(atIndex index: Int, of type: String.Type = String.self) -> String { - guard let cString = sqlite3_column_text(stmt, Int32(index)) else { - return "" - } - return String(cString: cString) - } - - public func columnValue(atIndex index: Int, of type: Data.Type = Data.self) -> Data { - guard let bytes = sqlite3_column_blob(stmt, Int32(index)) else { - return Data() - } - let count = Int(sqlite3_column_bytes(stmt, Int32(index))) - return Data(bytes: bytes, count: count) - } - - public func columnCount() -> Int { - return Int(sqlite3_column_count(stmt)) - } - - public func columnName(atIndex index: Int) -> String { - return String(cString: sqlite3_column_name(stmt, Int32(index))) - } - - public func columnTableName(atIndex index: Int) -> String { - return String(cString: sqlite3_column_table_name(stmt, Int32(index))) - } - - public func columnType(atIndex index: Int) -> ColumnType { - switch sqlite3_column_type(stmt, Int32(index)) { - case SQLITE_INTEGER: - return ColumnType.integer64 - case SQLITE_FLOAT: - return ColumnType.float - case SQLITE_BLOB: - return ColumnType.BLOB - case SQLITE_TEXT: - return ColumnType.text - default: - return ColumnType.null - } - } - - public var lastInsertedRowID: Int64 { - return sqlite3_last_insert_rowid(sqlite3_db_handle(stmt)) - } - - public func finalize() throws { - if stmt != nil { - let dbHandle = sqlite3_db_handle(stmt) - let rc = sqlite3_finalize(stmt) - stmt = nil - guard rc==SQLITE_OK else { - throw Error.reportSQLite(tag: handle.tag, - path: handle.path, - operation: .finalize, - extendedError: sqlite3_extended_errcode(dbHandle), - code: rc, - message: String(cString: sqlite3_errmsg(dbHandle)) - ) - } - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/JoinClause.swift b/Example/Pods/WCDB.swift/swift/source/abstract/JoinClause.swift deleted file mode 100644 index fae63806..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/JoinClause.swift +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class JoinClause: Describable { - public private(set) var description: String - - public enum JoinClauseType: Describable { - case left - case leftOuter - case inner - case cross - public var description: String { - switch self { - case .left: - return "LEFT" - case .leftOuter: - return "LEFT OUTER" - case .inner: - return "INNER" - case .cross: - return "CROSS" - } - } - } - - public init(with subqueryConvertible: TableOrSubqueryConvertible) { - description = subqueryConvertible.asTableOrSubquery().description - } - - @discardableResult - private func join(_ subqueryConvertible: TableOrSubqueryConvertible, - with type: JoinClauseType? = nil, - isNatural: Bool = false) -> JoinClause { - if isNatural { - description.append(" NATURAL") - } - if type != nil { - description.append(" \(type!.description)") - } - description.append(" JOIN \(subqueryConvertible.asTableOrSubquery().description)") - return self - } - - @discardableResult - public func join(_ subqueryConvertible: TableOrSubqueryConvertible, - with type: JoinClauseType? = nil) -> JoinClause { - return self.join(subqueryConvertible, with: type, isNatural: false) - } - - @discardableResult - public func natureJoin(_ subqueryConvertible: TableOrSubqueryConvertible, - with type: JoinClauseType? = nil) -> JoinClause { - return self.join(subqueryConvertible, with: type, isNatural: true) - } - - @discardableResult - public func on(_ expressionConvertible: ExpressionConvertible) -> JoinClause { - description.append(" ON \(expressionConvertible.asExpression().description)") - return self - } - - @discardableResult - public func using(_ columnConvertibleList: ColumnConvertible...) -> JoinClause { - return using(columnConvertibleList) - } - - @discardableResult - public func using(_ columnConvertibleList: [ColumnConvertible]) -> JoinClause { - description.append(" USING \(columnConvertibleList.joined())") - return self - } -} - -extension JoinClause: TableOrSubqueryConvertible { - public func asTableOrSubquery() -> Subquery { - return Subquery(with: self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/LiteralValue.swift b/Example/Pods/WCDB.swift/swift/source/abstract/LiteralValue.swift deleted file mode 100644 index 5756b447..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/LiteralValue.swift +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public struct LiteralValue: Describable { - public private(set) var description: String - - public init(_ value: Int32) { - description = String(value) - } - - public init(_ value: Int64) { - description = String(value) - } - - public init(_ value: Bool) { - description = String(value ? 1 : 0) - } - - public init(_ value: Double) { - description = String(value) - } - - public init(_ value: String) { - description = "'\(value.replacingOccurrences(of: "'", with: "''"))'" - } - - public init(_ value: Data) { - let string = String(data: value, encoding: .utf8) ?? "" - description = "'\(string.replacingOccurrences(of: "'", with: "''"))'" - } - - public init(_ value: Void?) { - description = "NULL" - } - - public init(_ value: FundamentalValue) { - switch value.type { - case .integer32: - self.init(value.int32Value) - case .integer64: - self.init(value.int64Value) - case .float: - self.init(value.doubleValue) - case .text: - self.init(value.stringValue) - case .BLOB: - self.init(value.dataValue) - case .null: - self.init(nil) - } - } - - public init(_ encodedValue: T) { - self.init(encodedValue.archivedValue()) - } -} - -extension LiteralValue: ExpressibleByNilLiteral { - public init(nilLiteral: ()) { - self.init(nilLiteral) - } -} - -extension LiteralValue: ExpressibleByIntegerLiteral { - public init(integerLiteral value: Int) { - self.init(value) - } -} - -extension LiteralValue: ExpressibleByBooleanLiteral { - public init(booleanLiteral value: Bool) { - self.init(value) - } -} - -extension LiteralValue: ExpressibleByFloatLiteral { - public init(floatLiteral value: Double) { - self.init(value) - } -} - -extension LiteralValue: ExpressibleByStringLiteral { - public init(stringLiteral value: String) { - self.init(value) - } -} - -extension LiteralValue: LiteralValueConvertible { - public func asLiteralValue() -> LiteralValue { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/ModuleArgument.swift b/Example/Pods/WCDB.swift/swift/source/abstract/ModuleArgument.swift deleted file mode 100644 index 862fbffd..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/ModuleArgument.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct ModuleArgument: Describable { - public private(set) var description: String - - public init(with tableConstraint: TableConstraint) { - description = tableConstraint.description - } - - public init(with columnDef: ColumnDef) { - description = columnDef.description - } - - public init(left: String, right: String) { - description = "\(left)=\(right)" - } - - public init(with tokenize: Tokenize) { - self.init(left: "tokenize", right: tokenize.module.name) - } - - public init(withTokenize tokenize: String) { - self.init(left: "tokenize", right: tokenize) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Operable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Operable.swift deleted file mode 100644 index 87138110..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Operable.swift +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -extension ExpressionConvertible { - static func operate(prefix: String, operand: ExpressionConvertible) -> Expression { - return Expression(withRaw: "(\(prefix)\(operand.asExpression().description))") - } - static func operate(title: String, infix: String?, operands: [ExpressionConvertible]) -> Expression { - return Expression(withRaw: "\(title)(\(infix != nil ? infix!+" " : "")\(operands.joined()))") - } - static func operate(operand: ExpressionConvertible, postfix: String) -> Expression { - return Expression(withRaw: "(\(operand.asExpression().description) \(postfix))") - } - static func operate(left: ExpressionConvertible, - `operator`: String, - right: ExpressionConvertible) -> Expression { - let leftDescription = left.asExpression().description - let rightDescription = right.asExpression().description - return Expression(withRaw: "(\(leftDescription) \(`operator`) \(rightDescription))") - } - static func operate(one: ExpressionConvertible, - operator1: String, - two: ExpressionConvertible, - operator2: String, - three: ExpressionConvertible) -> Expression { - let oneDescription = one.asExpression().description - let twoDescription = two.asExpression().description - let threeDescription = three.asExpression().description - let raws = [oneDescription, operator1, twoDescription, operator2, threeDescription] - return Expression(withRaw: "(\(raws.joined(separateBy: " ")))") - } -} - -public protocol ExpressionCanBeOperated: ExpressionConvertible { - static func || ( - left: Self, right: ExpressionOperableType) -> Expression - - static func && ( - left: Self, right: ExpressionOperableType) -> Expression - - static func * ( - left: Self, right: ExpressionOperableType) -> Expression - - static func / ( - left: Self, right: ExpressionOperableType) -> Expression - - static func % ( - left: Self, right: ExpressionOperableType) -> Expression - - static func + ( - left: Self, right: ExpressionOperableType) -> Expression - - static func - ( - left: Self, right: ExpressionOperableType) -> Expression - - static func << ( - left: Self, right: ExpressionOperableType) -> Expression - - static func >> ( - left: Self, right: ExpressionOperableType) -> Expression - - static func & ( - left: Self, right: ExpressionOperableType) -> Expression - - static func | ( - left: Self, right: ExpressionOperableType) -> Expression - - static func < ( - left: Self, right: ExpressionOperableType) -> Expression - - static func <= ( - left: Self, right: ExpressionOperableType) -> Expression - - static func > ( - left: Self, right: ExpressionOperableType) -> Expression - - static func >= ( - left: Self, right: ExpressionOperableType) -> Expression - - static func == ( - left: Self, right: ExpressionOperableType) -> Expression - - static func != ( - left: Self, right: ExpressionOperableType) -> Expression -} - -extension ExpressionCanBeOperated { - public static func || ( - left: Self, right: ExpressionOperableType) -> Expression { - return Expression.operate(left: left, operator: "OR", right: right) - } - - public static func && ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "AND", right: right) - } - - public static func * ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "*", right: right) - } - - public static func / ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "/", right: right) - } - - public static func % ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "%", right: right) - } - - public static func + ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "+", right: right) - } - - public static func - ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "-", right: right) - } - - public static func << ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "<<", right: right) - } - - public static func >> ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: ">>", right: right) - } - - public static func & ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "&", right: right) - } - - public static func | ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "|", right: right) - } - - public static func < ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "<", right: right) - } - - public static func <= ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "<=", right: right) - } - - public static func > ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: ">", right: right) - } - - public static func >= ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: ">=", right: right) - } - - public static func == ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "=", right: right) - } - - public static func != ( - left: Self, right: ExpressionOperableType) -> Expression { - return operate(left: left, operator: "!=", right: right) - } -} - -public protocol ExpressionOperable: ExpressionCanBeOperated { - //Unary - prefix static func ! (operand: Self) -> Expression - prefix static func + (operand: Self) -> Expression - prefix static func - (operand: Self) -> Expression - prefix static func ~ (operand: Self) -> Expression - - //Binary - static func || ( - left: Self, - right: ExpressionConvertibleType) -> Expression - - static func && ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func * - (left: Self, right: ExpressionConvertibleType) -> Expression - - static func / ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func % ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func + ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func - ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func << ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func >> ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func & ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func | ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func < ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func <= ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func > ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func >= ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func == ( - left: Self, right: ExpressionConvertibleType) -> Expression - - static func != ( - left: Self, right: ExpressionConvertibleType) -> Expression - - func concat(_ operand: ExpressionConvertible) -> Expression - func substr(start: ExpressionConvertible, length: ExpressionConvertible) -> Expression - - func like(_ operand: ExpressionConvertible) -> Expression - func glob(_ operand: ExpressionConvertible) -> Expression - func match(_ operand: ExpressionConvertible) -> Expression - func regexp(_ operand: ExpressionConvertible) -> Expression - - func notLike(_ operand: ExpressionConvertible) -> Expression - func notGlob(_ operand: ExpressionConvertible) -> Expression - func notMatch(_ operand: ExpressionConvertible) -> Expression - func notRegexp(_ operand: ExpressionConvertible) -> Expression - - func like(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func glob(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func match(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func regexp(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - - func notLike(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func notGlob(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func notMatch(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - func notRegexp(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression - - func isNull() -> Expression - func isNotNull() -> Expression - - func `is`(_ operand: ExpressionConvertible) -> Expression - func isNot(_ operand: ExpressionConvertible) -> Expression - - func between(_ begin: ExpressionConvertible, _ end: ExpressionConvertible) -> Expression - func notBetween(_ begin: ExpressionConvertible, _ end: ExpressionConvertible) -> Expression - - func `in`(_ statementSelect: StatementSelect) -> Expression - func notIn(_ statementSelect: StatementSelect) -> Expression - - func `in`(_ expressionConvertibleList: ExpressionConvertible...) -> Expression - func notIn(_ expressionConvertibleList: ExpressionConvertible...) -> Expression - - func `in`(_ expressionConvertibleList: [ExpressionConvertible]) -> Expression - func notIn(_ expressionConvertibleList: [ExpressionConvertible]) -> Expression - - //aggregate functions - func avg(isDistinct: Bool) -> Expression - func count(isDistinct: Bool) -> Expression - func groupConcat(isDistinct: Bool) -> Expression - func groupConcat(isDistinct: Bool, separateBy seperator: String) -> Expression - func max(isDistinct: Bool) -> Expression - func min(isDistinct: Bool) -> Expression - func sum(isDistinct: Bool) -> Expression - func total(isDistinct: Bool) -> Expression - - //core functions - func abs(isDistinct: Bool) -> Expression - func hex(isDistinct: Bool) -> Expression - func length(isDistinct: Bool) -> Expression - func lower(isDistinct: Bool) -> Expression - func upper(isDistinct: Bool) -> Expression - func round(isDistinct: Bool) -> Expression - - //FTS3 - func matchinfo() -> Expression - func offsets() -> Expression - func snippet() -> Expression -} - -extension ExpressionOperable { - //Unary - public prefix static func ! (operand: Self) -> Expression { - return operate(prefix: "NOT ", operand: operand) - } - public prefix static func + (operand: Self) -> Expression { - return operate(prefix: "", operand: operand) - } - public prefix static func - (operand: Self) -> Expression { - return operate(prefix: "-", operand: operand) - } - public prefix static func ~ (operand: Self) -> Expression { - return operate(prefix: "~", operand: operand) - } - - //Binary - public static func || ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "OR", right: right) - } - - public static func && ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "AND", right: right) - } - - public static func * ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "*", right: right) - } - - public static func / ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "/", right: right) - } - - public static func % ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "%", right: right) - } - - public static func + ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "+", right: right) - } - - public static func - ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "-", right: right) - } - - public static func << ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "<<", right: right) - } - - public static func >> ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: ">>", right: right) - } - - public static func & ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "&", right: right) - } - - public static func | ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "|", right: right) - } - - public static func < ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "<", right: right) - } - - public static func <= ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "<=", right: right) - } - - public static func > ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: ">", right: right) - } - - public static func >= ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: ">=", right: right) - } - - public static func == ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "=", right: right) - } - - public static func != ( - left: Self, right: ExpressionConvertibleType) -> Expression { - return operate(left: left, operator: "!=", right: right) - } - - public func concat(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "||", right: operand) - } - public func substr(start: ExpressionConvertible, length: ExpressionConvertible) -> Expression { - let description = asExpression().description - let startDescription = start.asExpression().description - let lengthDescription = length.asExpression().description - return Expression(withRaw: "SUBSTR(\(description), \(startDescription), \(lengthDescription))") - } - - public func like(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "LIKE", right: operand) - } - public func glob(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "GLOB", right: operand) - } - public func match(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "MATCH", right: operand) - } - public func regexp(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "REGEXP", right: operand) - } - public func notLike(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "NOT LIKE", right: operand) - } - public func notGlob(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "NOT GLOB", right: operand) - } - public func notMatch(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "NOT MATCH", right: operand) - } - public func notRegexp(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "NOT REGEXP", right: operand) - } - - public func like(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "LIKE", two: operand, operator2: "ESCAPE", three: escape) - } - public func glob(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "GLOB", two: operand, operator2: "ESCAPE", three: escape) - } - public func match(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "MATCH", two: operand, operator2: "ESCAPE", three: escape) - } - public func regexp(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "REGEXP", two: operand, operator2: "ESCAPE", three: escape) - } - public func notLike(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "NOT LIKE", two: operand, operator2: "ESCAPE", three: escape) - } - public func notGlob(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "NOT GLOB", two: operand, operator2: "ESCAPE", three: escape) - } - public func notMatch(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "NOT MATCH", two: operand, operator2: "ESCAPE", three: escape) - } - public func notRegexp(_ operand: ExpressionConvertible, escape: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "NOT REGEXP", two: operand, operator2: "ESCAPE", three: escape) - } - - public func isNull() -> Expression { - return Self.operate(operand: self, postfix: "ISNULL") - } - public func isNotNull() -> Expression { - return Self.operate(operand: self, postfix: "NOTNULL") - } - public func `is`(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "IS", right: operand) - } - public func isNot(_ operand: ExpressionConvertible) -> Expression { - return Self.operate(left: self, operator: "IS NOT", right: operand) - } - public func between(_ begin: ExpressionConvertible, _ end: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "BETWEEN", two: begin, operator2: "AND", three: end) - } - public func notBetween(_ begin: ExpressionConvertible, _ end: ExpressionConvertible) -> Expression { - return Self.operate(one: self, operator1: "NOT BETWEEN", two: begin, operator2: "AND", three: end) - } - - public func `in`(_ statementSelect: StatementSelect) -> Expression { - return Self.operate(prefix: "IN ", operand: statementSelect) - } - public func notIn(_ statementSelect: StatementSelect) -> Expression { - return Self.operate(prefix: "NOT IN ", operand: statementSelect) - } - public func `in`(_ expressionConvertibleList: ExpressionConvertible...) -> Expression { - return self.`in`(expressionConvertibleList) - } - public func notIn(_ expressionConvertibleList: ExpressionConvertible...) -> Expression { - return self.notIn(expressionConvertibleList) - } - public func `in`(_ expressionConvertibleList: [ExpressionConvertible]) -> Expression { - return Self.operate(operand: self, postfix: "IN(\(expressionConvertibleList.joined()))") - } - public func notIn(_ expressionConvertibleList: [ExpressionConvertible]) -> Expression { - return Self.operate(operand: self, postfix: "NOT IN(\(expressionConvertibleList.joined()))") - } - - //aggregate functions - public func avg(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "AVG", self, isDistinct: isDistinct) - } - public func count(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "COUNT", self, isDistinct: isDistinct) - } - public func groupConcat(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "GROUP_CONCAT", self, isDistinct: isDistinct) - } - public func groupConcat(isDistinct: Bool = false, separateBy seperator: String) -> Expression { - return Expression.function(named: "GROUP_CONCAT", self, seperator, isDistinct: isDistinct) - } - public func max(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "MAX", self, isDistinct: isDistinct) - } - public func min(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "MIN", self, isDistinct: isDistinct) - } - public func sum(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "SUM", self, isDistinct: isDistinct) - } - public func total(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "TOTAL", self, isDistinct: isDistinct) - } - //core functions - public func abs(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "ABS", self, isDistinct: isDistinct) - } - public func hex(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "HEX", self, isDistinct: isDistinct) - } - public func length(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "LENGTH", self, isDistinct: isDistinct) - } - public func lower(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "LOWER", self, isDistinct: isDistinct) - } - public func upper(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "UPPER", self, isDistinct: isDistinct) - } - public func round(isDistinct: Bool = false) -> Expression { - return Expression.function(named: "ROUND", self, isDistinct: isDistinct) - } - - //FTS3 - public func matchinfo() -> Expression { - return Expression.function(named: "MATCHINFO", self) - } - public func offsets() -> Expression { - return Expression.function(named: "OFFSETS", self) - } - public func snippet() -> Expression { - return Expression.function(named: "SNIPPET", self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Order.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Order.swift deleted file mode 100644 index 99344524..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Order.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct Order: Describable { - public private(set) var description: String - - public init(with expressionConvertible: ExpressionConvertible, by term: OrderTerm? = nil) { - description = "\(expressionConvertible.asExpression().description)\(term != nil ? " "+term!.description : "")" - } -} - -extension Order: OrderConvertible { - public func asOrder() -> Order { - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/OrderTerm.swift b/Example/Pods/WCDB.swift/swift/source/abstract/OrderTerm.swift deleted file mode 100644 index 335b6680..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/OrderTerm.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public enum OrderTerm: Describable { - case ascending - case descending - - public var description: String { - switch self { - case .ascending: - return "ASC" - case .descending: - return "DESC" - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Pragma.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Pragma.swift deleted file mode 100644 index e750505f..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Pragma.swift +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct Pragma: Describable { - public private(set) var description: String - - fileprivate init(named name: String) { - description = name - } - - public static let applicationId = Pragma(named: "application_id") - public static let autoVacuum = Pragma(named: "auto_vacuum") - public static let automaticIndex = Pragma(named: "automatic_index") - public static let busyTimeout = Pragma(named: "busy_timeout") - public static let cacheSize = Pragma(named: "cache_size") - public static let cacheSpill = Pragma(named: "cache_spill") - public static let caseSensitiveLike = Pragma(named: "case_sensitive_like") - public static let cellSizeCheck = Pragma(named: "cell_size_check") - public static let checkpointFullfsync = Pragma(named: "checkpoint_fullfsync") - public static let cipher = Pragma(named: "cipher") - public static let cipherAddRandom = Pragma(named: "cipher_add_random") - public static let cipherDefaultKdfIter = Pragma(named: "cipher_default_kdf_iter") - public static let cipherDefaultPageSize = Pragma(named: "cipher_default_page_size") - public static let cipherDefaultUseHmac = Pragma(named: "cipher_default_use_hmac") - public static let cipherMigrate = Pragma(named: "cipher_migrate") - public static let cipherProfile = Pragma(named: "cipher_profile") - public static let cipherProvider = Pragma(named: "cipher_provider") - public static let cipherProviderVersion = Pragma(named: "cipher_provider_version") - public static let cipherUseHmac = Pragma(named: "cipher_use_hmac") - public static let cipherVersion = Pragma(named: "cipher_version") - public static let cipherPageSize = Pragma(named: "cipher_page_size") - public static let collationList = Pragma(named: "collation_list") - public static let compileOptions = Pragma(named: "compile_options") - public static let countChanges = Pragma(named: "count_changes") - public static let dataStoreDirectory = Pragma(named: "data_store_directory") - public static let dataVersion = Pragma(named: "data_version") - public static let databaseList = Pragma(named: "database_list") - public static let defaultCacheSize = Pragma(named: "default_cache_size") - public static let deferForeignKeys = Pragma(named: "defer_foreign_keys") - public static let emptyResultCallbacks = Pragma(named: "empty_result_callbacks") - public static let encoding = Pragma(named: "encoding") - public static let foreignKeyCheck = Pragma(named: "foreign_key_check") - public static let foreignKeyList = Pragma(named: "foreign_key_list") - public static let foreignKeys = Pragma(named: "foreign_keys") - public static let freelistCount = Pragma(named: "freelist_count") - public static let fullColumnNames = Pragma(named: "full_column_names") - public static let fullfsync = Pragma(named: "fullfsync") - public static let ignoreCheckConstraints = Pragma(named: "ignore_check_constraints") - public static let incrementalVacuum = Pragma(named: "incremental_vacuum") - public static let indexInfo = Pragma(named: "index_info") - public static let indexList = Pragma(named: "index_list") - public static let indexXinfo = Pragma(named: "index_xinfo") - public static let integrityCheck = Pragma(named: "integrity_check") - public static let journalMode = Pragma(named: "journal_mode") - public static let journalSizeLimit = Pragma(named: "journal_size_limit") - public static let key = Pragma(named: "key") - public static let kdfIter = Pragma(named: "kdf_iter") - public static let legacyFileFormat = Pragma(named: "legacy_file_format") - public static let lockingMode = Pragma(named: "locking_mode") - public static let maxPageCount = Pragma(named: "max_page_count") - public static let mmapSize = Pragma(named: "mmap_size") - public static let pageCount = Pragma(named: "page_count") - public static let pageSize = Pragma(named: "page_size") - public static let parserTrace = Pragma(named: "parser_trace") - public static let queryOnly = Pragma(named: "query_only") - public static let quickCheck = Pragma(named: "quick_check") - public static let readUncommitted = Pragma(named: "read_uncommitted") - public static let recursiveTriggers = Pragma(named: "recursive_triggers") - public static let rekey = Pragma(named: "rekey") - public static let reverseUnorderedSelects = Pragma(named: "reverse_unordered_selects") - public static let schemaVersion = Pragma(named: "schema_version") - public static let secureDelete = Pragma(named: "secure_delete") - public static let shortColumnNames = Pragma(named: "short_column_names") - public static let shrinkMemory = Pragma(named: "shrink_memory") - public static let softHeapLimit = Pragma(named: "soft_heap_limit") - public static let stats = Pragma(named: "stats") - public static let synchronous = Pragma(named: "synchronous") - public static let tableInfo = Pragma(named: "table_info") - public static let tempStore = Pragma(named: "temp_store") - public static let tempStoreDirectory = Pragma(named: "temp_store_directory") - public static let threads = Pragma(named: "threads") - public static let userVersion = Pragma(named: "user_version") - public static let vdbeAddoptrace = Pragma(named: "vdbe_addoptrace") - public static let vdbeDebug = Pragma(named: "vdbe_debug") - public static let vdbeListing = Pragma(named: "vdbe_listing") - public static let vdbeTrace = Pragma(named: "vdbe_trace") - public static let walAutocheckpoint = Pragma(named: "wal_autocheckpoint") - public static let walCheckpoint = Pragma(named: "wal_checkpoint") - public static let writableSchema = Pragma(named: "writable_schema") -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Statement.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Statement.swift deleted file mode 100644 index c18b5a05..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Statement.swift +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public enum StatementType { - case alterTable - case createIndex - case createTable - case delete - case dropIndex - case dropTable - case insert - case pragma - case select - case transaction - case update - case createVirtualTable - case attach - case detach - case explain - case savepoint - case release - case rollback - case vacuum - case reindex -} - -public protocol Statement: Describable { - var statementType: StatementType {get} -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementAlterTable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementAlterTable.swift deleted file mode 100644 index 5e498989..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementAlterTable.swift +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class StatementAlterTable: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .alterTable - } - - public init() {} - - @discardableResult - public func alter(table: String) -> StatementAlterTable { - description.append("ALTER TABLE \(table)") - return self - } - - @discardableResult - public func rename(to newTable: String) -> StatementAlterTable { - description.append(" RENAME TO \(newTable)") - return self - } - - @discardableResult - public func addColumn(with columnDef: ColumnDef) -> StatementAlterTable { - description.append(" ADD COLUMN \(columnDef.description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementAttach.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementAttach.swift deleted file mode 100644 index 32a81cca..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementAttach.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementAttach: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .attach - } - - public init() {} - - @discardableResult - public func attach(_ expressionConvertible: ExpressionConvertible, asSchema schema: String) -> StatementAttach { - description.append("ATTACH \(expressionConvertible.asExpression().description) AS \(schema)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateIndex.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateIndex.swift deleted file mode 100644 index d23143ee..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateIndex.swift +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class StatementCreateIndex: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .createIndex - } - - public init() {} - - @discardableResult - public func create(index: String, isUnique: Bool = false, ifNotExists: Bool = true) -> StatementCreateIndex { - description.append("CREATE ") - if isUnique { - description.append("UNIQUE ") - } - description.append("INDEX ") - if ifNotExists { - description.append("IF NOT EXISTS ") - } - description.append(index) - return self - } - - @discardableResult - public func on(table: String, - indexesBy columnIndexConvertibleList: ColumnIndexConvertible...) -> StatementCreateIndex { - return on(table: table, indexesBy: columnIndexConvertibleList) - } - - @discardableResult - public func on(table: String, - indexesBy columnIndexConvertibleList: [ColumnIndexConvertible]) -> StatementCreateIndex { - description.append(" ON \(table)(\(columnIndexConvertibleList.joined()))") - return self - } - - @discardableResult - public func `where`(_ expressionConvertible: ExpressionConvertible) -> StatementCreateIndex { - let expression = expressionConvertible.asExpression() - if !expression.description.isEmpty { - description.append(" WHERE \(expression.description)") - } - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateTable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateTable.swift deleted file mode 100644 index 6a4b2e3f..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateTable.swift +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementCreateTable: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .createTable - } - - public init() {} - - @discardableResult - public func create(table: String, ifNotExists: Bool = true, - as statementSelect: StatementSelect) -> StatementCreateTable { - description.append("CREATE TABLE ") - if ifNotExists { - description.append("IF NOT EXISTS ") - } - description.append("\(table) AS \(statementSelect.description)") - return self - } - - @discardableResult - public func create(table: String, - ifNotExists: Bool = true, - with columnDefs: ColumnDef..., - and tableConstraints: [TableConstraint]? = nil) -> StatementCreateTable { - return self.create(table: table, ifNotExists: ifNotExists, with: columnDefs, and: tableConstraints) - } - - @discardableResult - public func create(table: String, - ifNotExists: Bool = true, - with columnDefs: [ColumnDef], - and optionalTableConstraints: [TableConstraint]? = nil) -> StatementCreateTable { - description.append("CREATE TABLE ") - if ifNotExists { - description.append("IF NOT EXISTS ") - } - description.append("\(table)(\(columnDefs.joined())") - if let tableConstraints = optionalTableConstraints { - description.append(", \(tableConstraints.joined())") - } - description.append(")") - return self - } - -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateVirtualTable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateVirtualTable.swift deleted file mode 100644 index aa19a8fc..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementCreateVirtualTable.swift +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementCreateVirtualTable: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .createVirtualTable - } - - public init() {} - - @discardableResult - public func create(virtualTable table: String, ifNotExists: Bool = true) -> StatementCreateVirtualTable { - description.append("CREATE VIRTUAL TABLE ") - if ifNotExists { - description.append("IF NOT EXISTS ") - } - description.append(table) - return self - } - - @discardableResult - public func using(module: String, arguments: [ModuleArgument]? = nil) -> StatementCreateVirtualTable { - description.append(" USING \(module)") - if arguments != nil && !arguments!.isEmpty { - description.append("(\(arguments!.joined()))") - } - return self - } - - @discardableResult - public func using(module: String, arguments: ModuleArgument...) -> StatementCreateVirtualTable { - return using(module: module, arguments: arguments) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDelete.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementDelete.swift deleted file mode 100644 index d90294ff..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDelete.swift +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementDelete: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .delete - } - - public init() {} - - @discardableResult - public func delete(fromTable table: String) -> StatementDelete { - description.append("DELETE FROM \(table)") - return self - } - - @discardableResult - public func `where`(_ expressionConvertible: ExpressionConvertible) -> StatementDelete { - let expression = expressionConvertible.asExpression() - if !expression.description.isEmpty { - description.append(" WHERE \(expression.description)") - } - return self - } - - @discardableResult - public func order(by orderConvertibleList: OrderConvertible...) -> StatementDelete { - return order(by: orderConvertibleList) - } - - @discardableResult - public func order(by orderConvertibleList: [OrderConvertible]) -> StatementDelete { - if !orderConvertibleList.isEmpty { - description.append(" ORDER BY \(orderConvertibleList.joined())") - } - return self - } - - @discardableResult - public func limit(from expressionConvertibleFrom: ExpressionConvertible, - to expressionConvertibleTo: ExpressionConvertible) -> StatementDelete { - let from = expressionConvertibleFrom.asExpression() - if !from.description.isEmpty { - description.append(" LIMIT \(from.description)") - let to = expressionConvertibleTo.asExpression() - if !to.description.isEmpty { - description.append(", \(to.description)") - } - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible) -> StatementDelete { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible, - offset expressionConvertibleOffset: ExpressionConvertible) -> StatementDelete { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - let offset = expressionConvertibleOffset.asExpression() - if !offset.description.isEmpty { - description.append(" OFFSET \(offset.description)") - } - } - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDetach.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementDetach.swift deleted file mode 100644 index c0687595..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDetach.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementDetach: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .detach - } - - public init() {} - - @discardableResult - public func detach(schema: String) -> StatementDetach { - description.append("DETACH \(schema)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropIndex.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropIndex.swift deleted file mode 100644 index fec25410..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropIndex.swift +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementDropIndex: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .dropIndex - } - - public init() {} - - @discardableResult - public func drop(index: String, ifExists: Bool = true) -> StatementDropIndex { - description.append("DROP INDEX ") - if ifExists { - description.append("IF EXISTS ") - } - description.append(index) - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropTable.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropTable.swift deleted file mode 100644 index c886aa80..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementDropTable.swift +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementDropTable: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .dropTable - } - - public init() {} - - public func drop(table: String, ifExists: Bool = true) -> StatementDropTable { - description.append("DROP TABLE ") - if ifExists { - description.append("IF EXISTS ") - } - description.append(table) - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementExplain.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementExplain.swift deleted file mode 100644 index 43034364..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementExplain.swift +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementExplain: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .explain - } - - public init() {} - - @discardableResult - public func explain(_ statement: Statement) -> StatementExplain { - description.append("EXPLAIN \(statement.description)") - return self - } - - @discardableResult - public func explainQueryPlan(_ statement: Statement) -> StatementExplain { - description.append("EXPLAIN QUERY PLAN \(statement.description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementInsert.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementInsert.swift deleted file mode 100644 index d3f31ff1..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementInsert.swift +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementInsert: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .insert - } - - public init() {} - - @discardableResult - public func insert(intoTable table: String, - with columnConvertibleList: ColumnConvertible..., - onConflict conflict: Conflict? = nil) -> StatementInsert { - return insert(intoTable: table, with: columnConvertibleList, onConflict: conflict) - } - - @discardableResult - public func insert(intoTable table: String, - with columnConvertibleList: [ColumnConvertible]? = nil, - onConflict conflict: Conflict? = nil) -> StatementInsert { - description.append("INSERT") - if conflict != nil { - description.append(" OR \(conflict!.description)") - } - description.append(" INTO \(table)") - if columnConvertibleList != nil { - description.append("(\(columnConvertibleList!.joined()))") - } - return self - } - - @discardableResult - public func values(_ expressionConvertibleList: ExpressionConvertible...) -> StatementInsert { - return values(expressionConvertibleList) - } - - @discardableResult - public func values(_ expressionConvertibleList: [ExpressionConvertible]) -> StatementInsert { - if !expressionConvertibleList.isEmpty { - description.append(" VALUES(\(expressionConvertibleList.joined()))") - } - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementPragma.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementPragma.swift deleted file mode 100644 index a54f9890..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementPragma.swift +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementPragma: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .pragma - } - - public init() {} - - @discardableResult - public func pragma(_ pragma: Pragma) -> StatementPragma { - description.append("PRAGMA \(pragma.description)") - return self - } - - @discardableResult - public func pragma(_ pragma: Pragma, to literalValueConvertible: LiteralValueConvertible) -> StatementPragma { - description.append("PRAGMA \(pragma.description)=\(literalValueConvertible.asLiteralValue().description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementReindex.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementReindex.swift deleted file mode 100644 index d2a2f16c..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementReindex.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementReindex: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .reindex - } - - public init() {} - - @discardableResult - public func reindex(_ name: String) -> StatementReindex { - description.append("REINDEX \(name)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementRelease.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementRelease.swift deleted file mode 100644 index 22c674be..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementRelease.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementRelease: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .release - } - - public init() {} - - @discardableResult - public func release(savepoint name: String) -> StatementRelease { - description.append("RELEASE \(name)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementRollback.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementRollback.swift deleted file mode 100644 index 8915b099..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementRollback.swift +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementRollback: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .rollback - } - - public init() {} - - public func rollback(toSavepoint optionalName: String? = nil) -> StatementRollback { - description.append("ROLLBACK") - if let name = optionalName { - description.append(" TO \(name)") - } - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementSavepoint.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementSavepoint.swift deleted file mode 100644 index 3e67882f..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementSavepoint.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementSavepoint: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .savepoint - } - - public init() {} - - @discardableResult - public func savepoint(_ name: String) -> StatementSavepoint { - description.append("SAVEPOINT \(name)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementSelect.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementSelect.swift deleted file mode 100644 index 35edd0bc..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementSelect.swift +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementSelect: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .select - } - - public init() {} - - @discardableResult - public func select(distinct: Bool = false, - _ columnResultConvertibleList: ColumnResultConvertible...) -> StatementSelect { - return select(distinct: distinct, columnResultConvertibleList) - } - - @discardableResult - public func select(distinct: Bool = false, - _ columnResultConvertibleList: [ColumnResultConvertible]) -> StatementSelect { - description.append("SELECT ") - if distinct { - description.append("DISTINCT ") - } - description.append(columnResultConvertibleList.joined()) - return self - } - - @discardableResult - public func from(_ tableOrSubqueryConvertibleList: TableOrSubqueryConvertible...) -> StatementSelect { - return from(tableOrSubqueryConvertibleList) - } - - @discardableResult - public func from(_ tableOrSubqueryConvertibleList: [TableOrSubqueryConvertible]) -> StatementSelect { - description.append(" FROM \(tableOrSubqueryConvertibleList.joined())") - return self - } - - @discardableResult - public func `where`(_ expressionConvertible: ExpressionConvertible) -> StatementSelect { - let expression = expressionConvertible.asExpression() - if !expression.description.isEmpty { - description.append(" WHERE \(expression.description)") - } - return self - } - - @discardableResult - public func order(by orderConvertibleList: OrderConvertible...) -> StatementSelect { - return order(by: orderConvertibleList) - } - - @discardableResult - public func order(by orderConvertibleList: [OrderConvertible]) -> StatementSelect { - if !orderConvertibleList.isEmpty { - description.append(" ORDER BY \(orderConvertibleList.joined())") - } - return self - } - - @discardableResult - public func limit(from expressionConvertibleFrom: ExpressionConvertible, - to expressionConvertibleTo: ExpressionConvertible) -> StatementSelect { - let from = expressionConvertibleFrom.asExpression() - if !from.description.isEmpty { - description.append(" LIMIT \(from.description)") - let to = expressionConvertibleTo.asExpression() - if !to.description.isEmpty { - description.append(", \(to.description)") - } - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible) -> StatementSelect { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible, - offset expressionConvertibleOffset: ExpressionConvertible) -> StatementSelect { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - let offset = expressionConvertibleOffset.asExpression() - if !offset.description.isEmpty { - description.append(" OFFSET \(offset.description)") - } - } - return self - } - - @discardableResult - public func group(by expressionConvertibleGroupList: ExpressionConvertible...) -> StatementSelect { - return group(by: expressionConvertibleGroupList) - } - - @discardableResult - public func group(by expressionConvertibleGroupList: [ExpressionConvertible]) -> StatementSelect { - if !expressionConvertibleGroupList.isEmpty { - description.append(" GROUP BY \(expressionConvertibleGroupList.joined())") - } - return self - } - - @discardableResult - public func having(_ expressionConvertibleHaving: ExpressionConvertible) -> StatementSelect { - let having = expressionConvertibleHaving.asExpression() - if !having.description.isEmpty { - description.append(" HAVING \(having.description)") - } - return self - } -} - -extension StatementSelect: ExpressionConvertible, TableOrSubqueryConvertible { - public func asExpression() -> Expression { - return Expression(with: self) - } - public func asTableOrSubquery() -> Subquery { - return Subquery(with: self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementTransaction.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementTransaction.swift deleted file mode 100644 index 8841336c..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementTransaction.swift +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementTransaction: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .transaction - } - - public init() {} - - public enum TransactionType: Describable { - case begin - case commit - case rollback - - public var description: String { - switch self { - case .begin: - return "BEGIN" - case .commit: - return "COMMIT" - case .rollback: - return "ROLLBACK" - } - } - } - - public private(set) var transactionType: TransactionType? - - public enum Mode: Describable { - case deferred - case immediate - case exclusive - - public var description: String { - switch self { - case .deferred: - return "DEFERRED" - case .immediate: - return "IMMEDIATE" - case .exclusive: - return "EXCLUSIVE" - } - } - } - - @discardableResult - public func begin(_ mode: Mode? = nil) -> StatementTransaction { - transactionType = .begin - description.append(transactionType!.description) - if mode != nil { - description.append(" \(mode!.description)") - } - return self - } - - @discardableResult - public func commit() -> StatementTransaction { - transactionType = .commit - description.append(transactionType!.description) - return self - } - - @discardableResult - public func rollback() -> StatementTransaction { - transactionType = .rollback - description.append(transactionType!.description) - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementUpdate.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementUpdate.swift deleted file mode 100644 index 9dff276e..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementUpdate.swift +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementUpdate: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .update - } - - public init() {} - - @discardableResult - public func update(table: String, onConflict conflict: Conflict? = nil) -> StatementUpdate { - description.append("UPDATE ") - if conflict != nil { - description.append("OR \(conflict!.description) ") - } - description.append(table) - return self - } - - public typealias ValueType = (_: ColumnConvertible, _: ExpressionConvertible) - - @discardableResult - public func set(_ values: [ValueType]) -> StatementUpdate { - let valueString = values.joined({ - $0.0.asColumn().description + "=" + $0.1.asExpression().description - }) - description.append(" SET \(valueString)") - return self - } - - @discardableResult - public func set(_ values: ValueType...) -> StatementUpdate { - return set(values) - } - - @discardableResult - public func `where`(_ expressionConvertible: ExpressionConvertible) -> StatementUpdate { - let expression = expressionConvertible.asExpression() - if !expression.description.isEmpty { - description.append(" WHERE \(expression.description)") - } - return self - } - - @discardableResult - public func order(by orderConvertibleList: OrderConvertible...) -> StatementUpdate { - return order(by: orderConvertibleList) - } - - @discardableResult - public func order(by orderConvertibleList: [OrderConvertible]) -> StatementUpdate { - if !orderConvertibleList.isEmpty { - description.append(" ORDER BY \(orderConvertibleList.joined())") - } - return self - } - - @discardableResult - public func limit(from expressionConvertibleFrom: ExpressionConvertible, - to expressionConvertibleTo: ExpressionConvertible) -> StatementUpdate { - let from = expressionConvertibleFrom.asExpression() - if !from.description.isEmpty { - description.append(" LIMIT \(from.description)") - let to = expressionConvertibleTo.asExpression() - if !to.description.isEmpty { - description.append(", \(to.description)") - } - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible) -> StatementUpdate { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - } - return self - } - - @discardableResult - public func limit(_ expressionConvertibleLimit: ExpressionConvertible, - offset expressionConvertibleOffset: ExpressionConvertible) -> StatementUpdate { - let limit = expressionConvertibleLimit.asExpression() - if !limit.description.isEmpty { - description.append(" LIMIT \(limit.description)") - let offset = expressionConvertibleOffset.asExpression() - if !offset.description.isEmpty { - description.append(" OFFSET \(offset.description)") - } - } - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/StatementVacuum.swift b/Example/Pods/WCDB.swift/swift/source/abstract/StatementVacuum.swift deleted file mode 100644 index fa66145c..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/StatementVacuum.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class StatementVacuum: Statement { - public private(set) var description: String = "" - public var statementType: StatementType { - return .vacuum - } - - public init() {} - - @discardableResult - public func vacuum(schema: String) -> StatementVacuum { - description.append("VACUUM \(schema)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Subquery.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Subquery.swift deleted file mode 100644 index 94310fd4..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Subquery.swift +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class Subquery: Describable { - public private(set) var description: String - - public init(with joinClause: JoinClause) { - description = "(\(joinClause.description))" - } - - public init(with statementSelect: StatementSelect) { - description = "(\(statementSelect.description))" - } - - public init(withTable table: String) { - description = table - } - - @discardableResult - public func `as`(alias: String) -> Subquery { - description.append(" AS \(alias)") - return self - } -} - -extension Subquery: TableOrSubqueryConvertible { - public func asTableOrSubquery() -> Subquery { - return self - } -} - -extension String: TableOrSubqueryConvertible { - public func asTableOrSubquery() -> Subquery { - return Subquery(withTable: self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/TableConstraint.swift b/Example/Pods/WCDB.swift/swift/source/abstract/TableConstraint.swift deleted file mode 100644 index 26531b11..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/TableConstraint.swift +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public final class TableConstraint: Describable { - public private(set) var description: String - - public init(named name: String) { - description = "CONSTRAINT \(name)" - } - - @discardableResult - public func makePrimary(indexesBy columnIndexConvertibleList: ColumnIndexConvertible...) -> TableConstraint { - return makePrimary(indexesBy: columnIndexConvertibleList) - } - - @discardableResult - public func makePrimary(indexesBy columnIndexConvertibleList: [ColumnIndexConvertible]) -> TableConstraint { - description.append(" PRIMARY KEY(\(columnIndexConvertibleList.joined()))") - return self - } - - @discardableResult - public func makeUnique(indexesBy columnIndexConvertibleList: ColumnIndexConvertible...) -> TableConstraint { - return makeUnique(indexesBy: columnIndexConvertibleList) - } - - @discardableResult - public func makeUnique(indexesBy columnIndexConvertibleList: [ColumnIndexConvertible]) -> TableConstraint { - description.append(" UNIQUE(\(columnIndexConvertibleList.joined()))") - return self - } - - @discardableResult - public func onConflict(_ conflict: Conflict) -> TableConstraint { - description.append(" ON CONFLICT \(conflict.description)") - return self - } - - @discardableResult - public func check(_ expressionConvertible: ExpressionConvertible) -> TableConstraint { - description.append(" CHECK\(expressionConvertible.asExpression().description)") - return self - } - - @discardableResult - public func makeForeignKey(_ columnConvertibleList: ColumnConvertible..., - foreignKey: ForeignKey) -> TableConstraint { - return makeForeignKey(columnConvertibleList, foreignKey: foreignKey) - } - - @discardableResult - public func makeForeignKey(_ columnConvertibleList: [ColumnConvertible], - foreignKey: ForeignKey) -> TableConstraint { - description.append(" FOREIGN KEY(\(columnConvertibleList.joined())) \(foreignKey.description)") - return self - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Tokenize.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Tokenize.swift deleted file mode 100644 index 8da40b8e..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Tokenize.swift +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol TokenizerInfoBase: AnyObject { - init(withArgc argc: Int32, andArgv argv: UnsafePointer?>?) -} - -public protocol CursorInfoBase: AnyObject { - init(withInput pInput: UnsafePointer?, - count: Int32, - tokenizerInfo: TokenizerInfoBase) - - func step(pToken: inout UnsafePointer?, - count: inout Int32, - startOffset: inout Int32, - endOffset: inout Int32, position: inout Int32) -> Int32 -} - -public protocol ModuleBase: AnyObject { - static var name: String {get} - - static var module: sqlite3_tokenizer_module {get} - - static var address: Data {get} - - static func create(argc: Int32, - argv: UnsafePointer?>?, - ppTokenizer: UnsafeMutablePointer?>?) -> Int32 - - static func destroy(pTokenizer optionalTokenizerPointer: UnsafeMutablePointer?) -> Int32 - - static func open(pTokenizer: UnsafeMutablePointer?, - pInput: UnsafePointer?, - nBytes: Int32, - ppCursor: UnsafeMutablePointer?>?) -> Int32 - - static func close(pCursor optionalCursorPointer: UnsafeMutablePointer?) -> Int32 - - static func next(pCursor optionalCursorPointer: UnsafeMutablePointer?, - ppToken: UnsafeMutablePointer?>?, - pnBytes: UnsafeMutablePointer?, - piStartOffset: UnsafeMutablePointer?, - piEndOffset: UnsafeMutablePointer?, - piPosition: UnsafeMutablePointer?) -> Int32 -} - -public protocol Module: ModuleBase { - associatedtype TokenizerInfo: TokenizerInfoBase - - associatedtype CursorInfo: CursorInfoBase -} - -extension Module { - public static func create(argc: Int32, - argv: UnsafePointer?>?, - ppTokenizer: UnsafeMutablePointer?>?) -> Int32 { - let tokenizerSize = MemoryLayout.size - let optionalTokenizerRawPointer = sqlite3_malloc(Int32(tokenizerSize)) - guard let tokenizerRawPointer = optionalTokenizerRawPointer else { - return SQLITE_NOMEM - } - memset(tokenizerRawPointer, 0, tokenizerSize) - - let info = TokenizerInfo(withArgc: argc, andArgv: argv) - let tokenizerPointer = tokenizerRawPointer.assumingMemoryBound(to: Tokenizer.self) - let opaqueInfo = Unmanaged.passRetained(info).toOpaque() - tokenizerPointer.pointee.info = opaqueInfo - - ppTokenizer!.pointee = tokenizerRawPointer.assumingMemoryBound(to: sqlite3_tokenizer.self) - - return SQLITE_OK - } - - public static func destroy(pTokenizer optionalTokenizerPointer: UnsafeMutablePointer?) -> Int32 { - if let tokenizerRawPointer = UnsafeMutableRawPointer(optionalTokenizerPointer) { - let tokenizerPointer = tokenizerRawPointer.assumingMemoryBound(to: Tokenizer.self) - Unmanaged.fromOpaque(tokenizerPointer.pointee.info).release() - sqlite3_free(tokenizerRawPointer) - } - return SQLITE_OK - } - - public static func open(pTokenizer: UnsafeMutablePointer?, - pInput: UnsafePointer?, - nBytes: Int32, - ppCursor: UnsafeMutablePointer?>?) -> Int32 { - var bytes: Int32 = nBytes - if pInput == nil { - bytes = 0 - }else if bytes < 0 { - bytes = Int32(strlen(pInput!)) - } - - let cursorSize = MemoryLayout.size - let optionalCursorRawPointer = sqlite3_malloc(Int32(cursorSize)) - guard let cursorRawPointer = optionalCursorRawPointer else { - return SQLITE_NOMEM - } - memset(cursorRawPointer, 0, cursorSize) - - let tokenizerPointer = UnsafeMutableRawPointer(pTokenizer!).assumingMemoryBound(to: Tokenizer.self) - let cursorPointer = cursorRawPointer.assumingMemoryBound(to: Cursor.self) - let tokenizerInfo = Unmanaged.fromOpaque(tokenizerPointer.pointee.info).takeUnretainedValue() - let cursorInfo = CursorInfo(withInput: pInput, count: bytes, tokenizerInfo: tokenizerInfo) - cursorPointer.pointee.info = Unmanaged.passRetained(cursorInfo).toOpaque() - - ppCursor!.pointee = cursorRawPointer.assumingMemoryBound(to: sqlite3_tokenizer_cursor.self) - - return SQLITE_OK - } - - public static func close(pCursor optionalCursorPointer: UnsafeMutablePointer?) -> Int32 { - if let cursorRawPointer = UnsafeMutableRawPointer(optionalCursorPointer) { - let cursorPointer = cursorRawPointer.assumingMemoryBound(to: Cursor.self) - Unmanaged.fromOpaque(cursorPointer.pointee.info).release() - sqlite3_free(cursorRawPointer) - } - return SQLITE_OK - } - - public static func next(pCursor optionalCursorPointer: UnsafeMutablePointer?, - ppToken: UnsafeMutablePointer?>?, - pnBytes: UnsafeMutablePointer?, - piStartOffset: UnsafeMutablePointer?, - piEndOffset: UnsafeMutablePointer?, - piPosition: UnsafeMutablePointer?) -> Int32 { - if let cursorRawPointer = UnsafeMutableRawPointer(optionalCursorPointer) { - let cursorPointer = cursorRawPointer.assumingMemoryBound(to: Cursor.self) - let cursorInfoPointer = Unmanaged.fromOpaque(cursorPointer.pointee.info) - - let rc = cursorInfoPointer.takeUnretainedValue().step(pToken: &ppToken!.pointee, - count: &pnBytes!.pointee, - startOffset: &piStartOffset!.pointee, - endOffset: &piEndOffset!.pointee, - position: &piPosition!.pointee) - return rc - } - return SQLITE_NOMEM - } -} - -public struct Tokenize { - let module: ModuleBase.Type -} - -public struct FTSModule { - public let name: String -} - -extension FTSModule { - public static let fts3 = FTSModule(name: "fts3") -} diff --git a/Example/Pods/WCDB.swift/swift/source/abstract/Tracer.swift b/Example/Pods/WCDB.swift/swift/source/abstract/Tracer.swift deleted file mode 100644 index ba4387ab..00000000 --- a/Example/Pods/WCDB.swift/swift/source/abstract/Tracer.swift +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class Tracer { - typealias SQLTracer = (String) -> Void // SQL - private var sqlTracer: SQLTracer? = nil { - didSet { - setup() - } - } - - typealias PerformanceTracer = ([String: Int], Int64, Any?) -> Void // (SQL, count), cost, userInfo - private var performanceTracer: PerformanceTracer? = nil { - didSet { - setup() - } - } - var shouldAggregation = false - private var footprint: [String: Int] = [:] - private var cost: Int64 = 0 - - private let handle: SQLite3 - var userInfo: Any? - - init(with handle: SQLite3) { - self.handle = handle - } - - deinit { - reportPerformance() - } - - struct TraceType: OptionSet { - let rawValue: UInt32 - - static let stmt = TraceType(rawValue: UInt32(SQLITE_TRACE_STMT)) - static let profile = TraceType(rawValue: UInt32(SQLITE_TRACE_PROFILE)) - } - - private var type: TraceType { - var type = TraceType() - if sqlTracer != nil { - type.insert(.stmt) - } - if performanceTracer != nil { - type.insert(.profile) - } - return type - } - - private func setup() { - let traceType = self.type - guard !traceType.isEmpty else { - sqlite3_trace_v2(handle, 0, nil, nil) - return - } - sqlite3_trace_v2(handle, traceType.rawValue, { (flag, context, stmtPointer, costPointer) -> Int32 in - let traceType = TraceType(rawValue: flag) - let pointer = Unmanaged.fromOpaque(context!) - let tracer = pointer.takeUnretainedValue() - - let stmt = OpaquePointer(stmtPointer) - guard let csql = sqlite3_sql(stmt) else { - return SQLITE_MISUSE - } - let sql = String(cString: csql) - switch traceType { - case .stmt: - tracer.report(sql: sql) - case .profile: - let cost: Int64 = UnsafePointer(OpaquePointer(costPointer)!).pointee - - //report last track - if !tracer.shouldAggregation { - tracer.reportPerformance() - } - - tracer.recordPerformance(sql: sql, cost: cost) - default: break - } - return SQLITE_OK - }, Unmanaged.passUnretained(self).toOpaque()) - } - - private func report(sql: String) { - guard let sqlTracer = self.sqlTracer else { - return - } - sqlTracer(sql) - } - - private func reportPerformance() { - guard !footprint.isEmpty else { - return - } - guard let performanceTracer = self.performanceTracer else { - return - } - performanceTracer(footprint, cost, userInfo) - footprint.removeAll() - cost = 0 - } - - private func recordPerformance(sql: String, cost: Int64) { - self.footprint[sql] = self.footprint[sql] ?? 1 - self.cost = cost - } - - func trace(sql sqlTracer: @escaping SQLTracer) { - self.sqlTracer = sqlTracer - } - - func track(performance performanceTracer: @escaping PerformanceTracer) { - self.performanceTracer = performanceTracer - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/builtin/CodableType.swift b/Example/Pods/WCDB.swift/swift/source/builtin/CodableType.swift deleted file mode 100644 index 528f09f1..00000000 --- a/Example/Pods/WCDB.swift/swift/source/builtin/CodableType.swift +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/* - * Builtin codable implementation - * - * .integer32: - * Bool, Int, Int8, Int16, Int32, UInt, UInt8, UInt16, UInt32 - * .integer64: - * Int64, UInt64 - * .float: - * Float, Double, Date - * .text: - * String, URL - * .BLOB: - * Data, Array, Dictionary, Set - * - */ - -//Bultin Column Codable -extension Int8: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toInt8() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension Int16: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toInt16() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension Int32: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self) - } -} - -extension Int64: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer64 - } - public init?(with value: FundamentalValue) { - self = value.int64Value - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self) - } -} - -extension Int: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer64 - } - public init?(with value: FundamentalValue) { - self = value.int64Value.toInt() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt64()) - } -} - -extension UInt8: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toUInt8() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension UInt16: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toUInt16() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension UInt32: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toUInt32() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension UInt64: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer64 - } - public init?(with value: FundamentalValue) { - self = value.int64Value.toUInt64() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt64()) - } -} - -extension UInt: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer64 - } - public init?(with value: FundamentalValue) { - self = value.int64Value.toUInt() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt64()) - } -} - -extension Bool: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .integer32 - } - public init?(with value: FundamentalValue) { - self = value.int32Value.toBool() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toInt32()) - } -} - -extension Float: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .float - } - public init?(with value: FundamentalValue) { - self = value.doubleValue.toFloat() - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.toDouble()) - } -} - -extension Double: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .float - } - public init?(with value: FundamentalValue) { - self = value.doubleValue - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self) - } -} - -extension String: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .text - } - public init?(with value: FundamentalValue) { - self = value.stringValue - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self) - } -} - -extension Data: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .BLOB - } - public init?(with value: FundamentalValue) { - self = value.dataValue - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self) - } -} - -extension Date: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .float - } - public init?(with value: FundamentalValue) { - self.init(timeIntervalSince1970: value.doubleValue) - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(timeIntervalSince1970) - } -} - -extension URL: ColumnCodable, LiteralValueConvertible, ExpressionCanBeOperated { - public static var columnType: ColumnType { - return .text - } - public init?(with value: FundamentalValue) { - self.init(string: value.stringValue) - } - public func archivedValue() -> FundamentalValue { - return FundamentalValue(self.absoluteString) - } -} - -extension Array: ColumnCodable, ColumnCodableBase where Element: Codable { - public static var columnType: ColumnType { - return .BLOB - } - public init?(with value: FundamentalValue) { - guard let decodable = try? JSONDecoder().decode(Array.self, from: value.dataValue) else { - return nil - } - self = decodable - } - public func archivedValue() -> FundamentalValue { - guard let encoded = try? JSONEncoder().encode(self) else { - return FundamentalValue(nil) - } - return FundamentalValue(encoded) - } -} - -extension Dictionary: ColumnCodable, ColumnCodableBase where Key: Codable, Value: Codable { - public static var columnType: ColumnType { - return .BLOB - } - public init?(with value: FundamentalValue) { - guard let decodable = try? JSONDecoder().decode(Dictionary.self, from: value.dataValue) else { - return nil - } - self = decodable - } - public func archivedValue() -> FundamentalValue { - guard let encoded = try? JSONEncoder().encode(self) else { - return FundamentalValue(nil) - } - return FundamentalValue(encoded) - } -} - -extension Set: ColumnCodable, ColumnCodableBase where Element: Codable { - public static var columnType: ColumnType { - return .BLOB - } - public init?(with value: FundamentalValue) { - guard let decodable = try? JSONDecoder().decode(Set.self, from: value.dataValue) else { - return nil - } - self = decodable - } - public func archivedValue() -> FundamentalValue { - guard let encoded = try? JSONEncoder().encode(self) else { - return FundamentalValue(nil) - } - return FundamentalValue(encoded) - } -} - -//JSONCodable -public protocol ColumnJSONEncodable: ColumnEncodable {} -extension ColumnJSONEncodable { - public func archivedValue() -> FundamentalValue { - guard let encoded = try? JSONEncoder().encode(self) else { - return FundamentalValue(nil) - } - return FundamentalValue(encoded) - } -} - -public protocol ColumnJSONDecodable: ColumnDecodable {} -extension ColumnJSONDecodable { - public init?(with value: FundamentalValue) { - guard let decodable = try? JSONDecoder().decode(Self.self, from: value.dataValue) else { - return nil - } - self = decodable - } -} - -public protocol ColumnJSONCodable: ColumnJSONEncodable, ColumnJSONDecodable {} -extension ColumnJSONCodable { - public static var columnType: ColumnType { - return .BLOB - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/builtin/CommonStatement.swift b/Example/Pods/WCDB.swift/swift/source/builtin/CommonStatement.swift deleted file mode 100644 index 49fe4a35..00000000 --- a/Example/Pods/WCDB.swift/swift/source/builtin/CommonStatement.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class CommonStatement { - public static let enableFullfsync = StatementPragma().pragma(.fullfsync, to: true) - - public static let getJournalMode = StatementPragma().pragma(.journalMode) - public static let enableJournalModeWAL = StatementPragma().pragma(.journalMode, to: "WAL") - - public static let enableSynchronousNormal = StatementPragma().pragma(.synchronous, to: "NORMAL") - public static let enableSynchronousFull = StatementPragma().pragma(.synchronous, to: "FULL") - - public static let getLockingMode = StatementPragma().pragma(.lockingMode) - public static let enableLockingModeNormal = StatementPragma().pragma(.lockingMode, to: "NORMAL") - - public static let checkpoint = StatementPragma().pragma(.walCheckpoint) - - public static let fts3Tokenizer = StatementSelect() - .select(Expression.function(named: "fts3_tokenizer", - Array(repeating: Expression.bindParameter, count: 2)) - ) - - public static let beginTransactionImmediate = StatementTransaction().begin(.immediate) - public static let commitTransaction = StatementTransaction().commit() - public static let rollbackTransaction = StatementTransaction().rollback() -} diff --git a/Example/Pods/WCDB.swift/swift/source/builtin/Master.swift b/Example/Pods/WCDB.swift/swift/source/builtin/Master.swift deleted file mode 100644 index 1e336d77..00000000 --- a/Example/Pods/WCDB.swift/swift/source/builtin/Master.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct Master: TableCodable { - public static let builtinTableName: String = "sqlite_master" - - public var type: String? - public var name: String? - public var tableName: String? - public var rootpage: Int? - public var sql: String? - - public enum CodingKeys: String, CodingTableKey { - public typealias Root = Master - - case type - case name - case tableName = "tbl_name" - case rootpage - case sql - - public static let objectRelationalMapping = TableBinding(Master.CodingKeys.self) - } - - public init() {} -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/Config.swift b/Example/Pods/WCDB.swift/swift/source/core/base/Config.swift deleted file mode 100644 index 9ca09e68..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/Config.swift +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -//TODO: refactor for configs -public struct Configs { - public typealias Callback = Config.Callback - public typealias Order = Config.Order - - public struct Config: Equatable { - public typealias Callback = (Handle) throws -> Void - typealias TaggedCallback = Tagged - public typealias Order = Int - - let name: String - let callback: TaggedCallback? - let order: Order - - init(named name: String, with callback: @escaping Callback, orderBy order: Order) { - self.name = name - self.callback = Tagged(callback) - self.order = order - } - - init(emptyConfigNamed name: String, orderBy order: Order) { - self.name = name - self.callback = nil - self.order = order - } - - public static func == (lhs: Config, rhs: Config) -> Bool { - return lhs.name == rhs.name && lhs.callback == rhs.callback && lhs.order == rhs.order - } - } - - private var configs = ContiguousArray() - - init(_ configs: ContiguousArray) { - self.configs = configs - } - - mutating func setConfig(named name: String, with callback: @escaping Callback, orderBy order: Order) { - var inserted: Bool = false - var newConfigs: ContiguousArray = configs.reduce(into: ContiguousArray()) { (result, config) in - if !inserted && order < config.order { - result.append(Config(named: name, with: callback, orderBy: order)) - inserted = true - } else if name != config.name { - result.append(config) - } - } - if !inserted { - newConfigs.append(Config(named: name, with: callback, orderBy: order)) - } - configs = newConfigs - } - - mutating func setConfig(named name: String, with callback: @escaping Callback) { - var inserted: Bool = false - var newConfigs: ContiguousArray = configs.reduce(into: ContiguousArray()) { (result, config) in - if name != config.name { - result.append(config) - } else { - result.append(Config(named: name, with: callback, orderBy: config.order)) - inserted = true - } - } - if !inserted { - newConfigs.append(Config(named: name, with: callback, orderBy: Order.max)) - } - configs = newConfigs - } - - func invoke(handle: Handle) throws { - let configs = self.configs - for config in configs { - try config.callback?.value(handle) - } - } - - func config(by name: String) -> Callback? { - let configs = self.configs - return configs.first { $0.name == name }?.callback?.value - } -} - -extension Configs: Equatable { - public static func == (lhs: Configs, rhs: Configs) -> Bool { - guard lhs.configs.count == rhs.configs.count else { - return false - } - for i in 0.. RecyclableHandleStatement { - assert(statement.statementType != .transaction, - "Using [begin], [commit], [rollback] or [Exec] method to do a transaction") - let handleStatement = try recyclableHandle.raw.handle.prepare(statement) - return RecyclableHandleStatement(recyclableHandle: recyclableHandle, handleStatement: handleStatement) - } - - final func exec(_ statement: Statement, in recyclableHandle: RecyclableHandle) throws { - assert(statement.statementType != .transaction, - "Using [begin], [commit], [rollback] method to do a transaction") - return try recyclableHandle.raw.handle.exec(statement) - } - - func prepare(_ statement: Statement) throws -> RecyclableHandleStatement { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func exec(_ statement: Statement) throws { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - /// Prepare a specific sql. - /// Note that you can use this interface to prepare a SQL that is not contained in the WCDB interface layer - /// - /// - Parameter statement: WINQ statement - /// - Returns: CoreStatement - /// - Throws: `Error` - public func prepare(_ statement: Statement) throws -> CoreStatement { - return CoreStatement(with: self, and: try prepare(statement)) - } - - public func isTableExists(_ table: String) throws -> Bool { - let statementSelect = StatementSelect().select(1).from(table).limit(0) - Error.threadedSlient.value = true; defer { Error.threadedSlient.value = false } - do { - let handleStatement: RecyclableHandleStatement = try prepare(statementSelect) - try handleStatement.raw.step() - return true - } catch let error as Error { - guard error.code.value == Int(SQLITE_ERROR) else { - throw error - } - } - return false - } - - func begin(_ mode: StatementTransaction.Mode = .immediate) throws { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func commit() throws { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func rollback() throws { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - public typealias TransactionClosure = () throws -> Void - - public typealias ControlableTransactionClosure = () throws -> Bool - - /// Run a transaction in closure - /// - /// try database.run(transaction: { () throws -> Void in - /// try database.insert(objects: objects, intoTable: table) - /// }) - /// - /// - Parameter transaction: Operation inside transaction - /// - Throws: `Error` - public func run(transaction: TransactionClosure) throws { - try begin(.immediate) - do { - try transaction() - try commit() - } catch let error { - try? rollback() - throw error - } - } - - /// Run a controllable transaction in closure - /// - /// try database.run(controllableTransaction: { () throws -> Bool in - /// try database.insert(objects: objects, intoTable: table) - /// return true // return true to commit transaction and return false to rollback transaction. - /// }) - /// - /// - Parameter controllableTransaction: Operation inside transaction - /// - Throws: `Error` - public func run(controllableTransaction: ControlableTransactionClosure) throws { - try begin(.immediate) - var shouldRollback = true - do { - if try controllableTransaction() { - try commit() - } else { - shouldRollback = false - try rollback() - } - } catch let error { - if shouldRollback { - try? rollback() - } - throw error - } - } - - func run(embeddedTransaction: TransactionClosure) throws { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } -} - -protocol CoreRepresentable: AnyObject { - var tag: Tag? {get} - var path: String {get} -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/CoreStatement.swift b/Example/Pods/WCDB.swift/swift/source/core/base/CoreStatement.swift deleted file mode 100644 index 97f87709..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/CoreStatement.swift +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// CoreStatement for preparing or executing WINQ sql. -public final class CoreStatement { - private let core: Core - private let recyclableHandleStatement: RecyclableHandleStatement - - init(with core: Core, and recyclableHandleStatement: RecyclableHandleStatement) { - self.core = core - self.recyclableHandleStatement = recyclableHandleStatement - } - - private var handleStatement: HandleStatement { - return recyclableHandleStatement.raw - } - - /// The wrapper of `sqlite3_bind_*` for binding property of object to index. - /// - /// - Parameters: - /// - propertyConvertible: `Property` or `CodingTableKey` - /// - object: Table encodable object - /// - index: Begin with 1 - /// - Throws: `Error` - public func bind( - _ propertyConvertible: PropertyConvertible, - of object: TableEncodableType, - toIndex index: Int = 1) throws { - try bind([(propertyConvertible, toIndex: index)], of: object) - } - - /// The wrapper of `sqlite3_bind_*` for binding properties of object to indexes. - /// - /// - Parameters: - /// - indexedPropertyConvertibleList: Indexed `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - Throws: Begin with 1 - public func bind( - _ indexedPropertyConvertibleList: [(_: PropertyConvertible, toIndex: Int)], - of object: TableEncodableType) throws { - var hashedKeys: TableEncoder.HashedKey = [:] - for args in indexedPropertyConvertibleList { - hashedKeys[args.0.codingTableKey.stringValue.hashValue] = args.toIndex - } - let encoder = TableEncoder(hashedKeys, on: recyclableHandleStatement) - try object.encode(to: encoder) - } - - /// The wrapper of `sqlite3_bind_*` for binding properties of object. - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - Throws: Begin with 1 - public func bind( - _ propertyConvertibleList: [PropertyConvertible], - of object: TableEncodableType) throws { - var hashedKeys: TableEncoder.HashedKey = [:] - for (index, propertyConvertible) in propertyConvertibleList.enumerated() { - hashedKeys[propertyConvertible.codingTableKey.stringValue.hashValue] = index - } - let encoder = TableEncoder(hashedKeys, on: recyclableHandleStatement) - try object.encode(to: encoder) - } - - /// The wrapper of `sqlite3_bind_*` for binding column encodable object. - /// - /// - Parameters: - /// - value: Column encodable object - /// - index: Begin with 1 - public func bind(_ value: ColumnEncodable?, toIndex index: Int) { - guard let bindingValue = value?.archivedValue() else { - handleStatement.bind(nil, toIndex: index) - return - } - handleStatement.bind(bindingValue, toIndex: index) - } - - /// The wrapper of `sqlite3_column_*` for getting column decodable value. - /// - /// - Parameters: - /// - index: Begin with 0 - /// - type: Type of column codable object - /// - Returns: Same as type - public func value(atIndex index: Int, of type: ColumnDecodable.Type) -> ColumnDecodable? { - guard handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return type.init(with: handleStatement.columnValue(atIndex: index)) - } - - /// The wrapper of `sqlite3_column_*` for getting column decodable value. - /// - /// - Parameters: - /// - index: Begin with 0 - /// - type: Type of column codable object - /// - Returns: Same as type - public func value( - atIndex index: Int, - of type: ColumnDecodableType.Type = ColumnDecodableType.self) -> ColumnDecodableType? { - guard handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return type.init(with: handleStatement.columnValue(atIndex: index)) - } - - /// The wrapper of `sqlite3_column_*` for getting fundamentable value. - /// - /// - Parameter index: Begin with 0 - /// - Returns: `Int32`, `Int64`, `Double`, `String`, `Data` or `nil` value. - public func value(atIndex index: Int) -> FundamentalValue { - switch handleStatement.columnType(atIndex: index) { - case .integer32: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Int32.self)) - case .integer64: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Int64.self)) - case .float: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Double.self)) - case .text: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: String.self)) - case .BLOB: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Data.self)) - case .null: - return FundamentalValue(nil) - } - } - - /// The wrapper of `sqlite3_column_*` for getting column decodable value. - /// - /// - Parameters: - /// - name: Name of the column - /// - type: Type of column codable object - /// - Returns: Same as type. Nil will be returned if no such a column. - public func value( - byName name: String, - of type: ColumnDecodableType.Type = ColumnDecodableType.self) -> ColumnDecodableType? { - guard let index = index(byName: name) else { - return nil - } - return value(atIndex: index) - } - - /// Get index by column name. - /// - /// - Parameter name: Name of the column - /// - Returns: Index of given column name. Nil will be returned if no such a column. - public func index(byName name: String) -> Int? { - for index in 0.. Bool { - return try handleStatement.step() - } - - /// The wrapper of `sqlite3_reset` - /// - /// - Throws: `Error` - public func reset() throws { - try handleStatement.reset() - } - - /// The wrapper of `sqlite3_column_type` - /// - /// - Parameter index: Begin with 0 - /// - Returns: Type of the column - public func columnType(atIndex index: Int) -> ColumnType { - return handleStatement.columnType(atIndex: index) - } - - /// The wrapper of `sqlite3_column_type` - /// - /// - Parameter name: Name of the column - /// - Returns: Column type. For a non-exists column, `.null` will be returned. - public func columnType(byName name: String) -> ColumnType { - guard let index = index(byName: name) else { - return .null - } - return columnType(atIndex: index) - } - - /// The wrapper of `sqlite3_column_count`. - /// - /// - Returns: Count of column result - public func columnCount() -> Int { - return handleStatement.columnCount() - } - - /// The wrapper of `sqlite3_column_name`. - /// - /// - Parameter index: Begin with 0 - /// - Returns: Column name - public func columnName(atIndex index: Int) -> String { - return handleStatement.columnName(atIndex: index) - } - - /// The wrapper of `sqlite3_column_table_name`. - /// - /// - Parameter index: Begin with 0 - /// - Returns: The related table of column at index - public func columnTableName(atIndex index: Int) -> String { - return handleStatement.columnTableName(atIndex: index) - } - - /// The wrapper of `sqlite3_finalize` - /// - /// - Throws: `Error` - public func finalize() throws { - try handleStatement.finalize() - } - - /// The number of changed rows in the most recent call. - /// It should be called after executing successfully - public var changes: Int { - return handleStatement.changes - } - - /// The row id of most recent insertion. - public var lastInsertedRowID: Int64 { - return handleStatement.lastInsertedRowID - } -} - -extension CoreStatement { - - /// The tag of the related database. - public var tag: Tag? { - return core.tag - } - - /// The path of the related database. - public var path: String { - return core.path - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/Database.swift b/Example/Pods/WCDB.swift/swift/source/core/base/Database.swift deleted file mode 100644 index b890ce24..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/Database.swift +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -#if WCDB_IOS -import UIKit -#endif //WCDB_IOS - -/// Thread-safe Database object -public final class Database: Core { - - /// Init a database from path. - /// Note that all database objects with same path share the same core. - /// So you can create multiple database objects. WCDB will manage them automatically. - /// Note that WCDB will not generate a sqlite handle until the first operation, - /// which is also called as lazy initialization. - /// - /// - Parameter path: Path to your database - public convenience init(withPath path: String) { - self.init(withFileURL: URL(fileURLWithPath: path)) - } - - /// Init a database from file url. - /// Note that all database objects with same path share the same core. - /// So you can create multiple database objects. WCDB will manage them automatically. - /// Note that WCDB will not generate a sqlite handle until the first operation, - /// which is also called as lazy initialization. - /// - /// - Parameter url: File url to your database - public init(withFileURL url: URL) { - #if swift(>=4.2) - #else - Error.fatalError("Swift 4.2 is required.") - #endif - #if WCDB_IOS - DispatchQueue.once(name: "com.Tencent.WCDB.swift.purge", { - let purgeFreeHandleQueue: DispatchQueue = DispatchQueue(label: "com.Tencent.WCDB.swift.purge") - _ = NotificationCenter.default.addObserver( - forName: UIApplication.didReceiveMemoryWarningNotification, - object: nil, - queue: nil, - using: { (_) in - purgeFreeHandleQueue.async { - Database.purge() - } - }) - }) - #endif //WCDB_IOS - super.init(with: HandlePool.getPool(withPath: url.standardizedFileURL.path, - defaultConfigs: Database.defaultConfigs)) - } - - /// Init a database from existing tag. - /// Note that all database objects with same path share the same core. - /// So you can create multiple database objects. WCDB will manage them automatically. - /// Note that WCDB will not generate a sqlite handle until the first operation, - /// which is also called as lazy initialization. - /// - /// - Parameter tag: An existing tag. - /// - Throws: `Error` while tag is not exists - public init(withExistingTag tag: Tag) throws { - super.init(with: try HandlePool.getExistingPool(with: tag)) - } - - init(withExistingPath path: String) throws { - super.init(with: try HandlePool.getExistingPool(withPath: path)) - } - - /// The tag of the database. Default to nil. - /// You should set it on a database and can get it from all kind of Core objects, - /// including `Database`, `Table`, `Transaction`, `Select`, `RowSelect`, `MultiSelect`, `Insert`, `Delete`, - /// `Update` and so on. - /// Note that core objects with same path share this tag, even they are not the same object. - /// - /// let database1 = Database(withPath: path) - /// let database2 = Database(withPath: path) - /// database1.tag = 1 - /// print("Tag: \(database2.tag!)") // print 1 - /// - public override var tag: Tag? { - get { - return handlePool.tag - } - set { - handlePool.tag = newValue - } - } - - private static var threadedHandles = ThreadLocal<[String: RecyclableHandle]>(defaultTo: [:]) - - private func flowOut() throws -> RecyclableHandle { - let threadedHandles = Database.threadedHandles.value - if let handle = threadedHandles[path] { - return handle - } - return try handlePool.flowOut() - } - - /// Since WCDB is using lazy initialization, - /// `init(withPath:)`, `init(withFileURL:)` never failed even the database can't open. - /// So you can call this to check whether the database can be opened. - /// Return false if an error occurs during sqlite handle initialization. - public var canOpen: Bool { - return !handlePool.isDrained || ((try? handlePool.fillOne()) != nil) - } - - /// Check database is already opened. - public var isOpened: Bool { - return !handlePool.isDrained - } - - /// Check whether database is blockaded. - public var isBlockaded: Bool { - return handlePool.isBlockaded - } - - public typealias OnClosed = HandlePool.OnDrained - - /// Close the database. - /// Since Multi-threaded operation is supported in WCDB, - /// other operations in different thread can open the closed database. - /// So this method can make sure database is closed in the `onClosed` block. - /// All other operations will be blocked until this method returns. - /// - /// A close operation consists of 4 steps: - /// 1. `blockade`, which blocks all other operations. - /// 2. `close`, which waits until all sqlite handles return and closes them. - /// 3. `onClosed`, which trigger the callback. - /// 4. `unblokade`, which unblocks all other opreations. - /// - /// You can simply call `close:` to do all steps above or call these separately. - /// Since this method will wait until all sqlite handles return, it may lead to deadlock in some bad practice. - /// The key to avoid deadlock is to make sure all WCDB objects in current thread is dealloced. In detail: - /// 1. You should not keep WCDB objects, including `Insert`, `Delete`, `Update`, `Select`, `RowSelect`, - /// `MultiSelect`, `CoreStatement`, `Transaction`. These objects should not be kept. - /// You should get them, use them, then release them right away. - /// 2. WCDB objects may not be out of its' scope. - /// The best practice is to call `close:` in sub-thread and display a loading animation in main thread. - /// - /// //close directly - /// database.close(onClosed: { () throws -> Void in - /// //do something on this closed database - /// }) - /// - /// //close separately - /// database.blockade() - /// database.close() - /// //do something on this closed database - /// database.unblockade() - /// - /// - Parameter onClosed: Trigger on database closed. - /// - Throws: Rethrows your error. - public func close(onClosed: OnClosed) rethrows { - try handlePool.drain(onDrained: onClosed) - } - - /// Close the database. - public func close() { - handlePool.drain() - } - - /// Blockade the database. - public func blockade() { - handlePool.blockade() - } - - /// Unblockade the database. - public func unblockade() { - handlePool.unblockade() - } - - /// Purge all unused memory of this database. - /// WCDB will cache and reuse some sqlite handles to improve performance. - /// The max count of free sqlite handles is same - /// as the number of concurrent threads supported by the hardware implementation. - /// You can call it to save some memory. - public func purge() { - handlePool.purgeFreeHandles() - } - - /// Purge all unused memory of all databases. - /// Note that WCDB will call this interface automatically while it receives memory warning on iOS. - public static func purge() { - HandlePool.purgeFreeHandlesInAllPools() - } - - override func prepare(_ statement: Statement) throws -> RecyclableHandleStatement { - let recyclableHandle = try flowOut() - return try prepare(statement, in: recyclableHandle) - } - - /// Exec a specific sql. - /// Note that you can use this interface to execute a SQL that is not contained in the WCDB interface layer. - /// - /// - Parameter statement: WINQ statement - /// - Throws: `Error` - public override func exec(_ statement: Statement) throws { - try exec(statement, in: flowOut()) - } - - /// Separate interface of `run(transaction:)` - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// To do a cross-thread transaction, use `getTransaction`. - /// - Throws: `Error` - public override func begin(_ mode: StatementTransaction.Mode = .immediate) throws { - let statement = mode == .immediate ? - CommonStatement.beginTransactionImmediate : - StatementTransaction().begin(mode) - let recyableHandlePool = try flowOut() - try recyableHandlePool.raw.handle.exec(statement) - Database.threadedHandles.value[path] = recyableHandlePool - } - - /// Separate interface of `run(transaction:)` - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// To do a cross-thread transaction, use `getTransaction`. - /// - Throws: `Error` - public override func commit() throws { - let recyableHandlePool = try flowOut() - try recyableHandlePool.raw.handle.exec(CommonStatement.commitTransaction) - Database.threadedHandles.value.removeValue(forKey: path) - } - - /// Separate interface of run(transaction:) - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// To do a cross-thread transaction, use `getTransaction`. - /// - Throws: `Error` - public override func rollback() throws { - Database.threadedHandles.value.removeValue(forKey: path) - let recyableHandlePool = try flowOut() - try recyableHandlePool.raw.handle.exec(CommonStatement.rollbackTransaction) - } - - /// Run a embedded transaction in closure - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// try database.run(embeddedTransaction: { () throws -> Void in - /// try database.insert(objects: objects, intoTable: table) - /// }) - /// - /// - Parameter embeddedTransaction: Operation inside transaction - /// - Throws: `Error` - public override func run(embeddedTransaction: TransactionClosure) throws { - if Database.threadedHandles.value[path] != nil { - return try embeddedTransaction() - } - return try run(transaction: embeddedTransaction) - } -} - -//Config -extension Database { - - /// Set cipher key for a database. - /// For an encrypted database, you must call it before all other operation. - /// The cipher page size defaults to 4096 in WCDB, but it defaults to 1024 in other databases. - /// So for an existing database created by other database framework, you should set it to 1024. - /// Otherwise, you'd better to use cipher page size with 4096 - /// or simply call setCipherKey: interface to get better performance. - /// - /// - Parameters: - /// - optionalKey: Cipher key. Nil for no cipher. - /// - pageSize: Cipher page size. - public func setCipher(key optionalKey: Data?, pageSize: Int = 4096) { - if let key = optionalKey { - handlePool.setConfig(named: DefaultConfigOrder.cipher.description, with: { (handle: Handle) throws in - let statementPragmaPageSize = StatementPragma().pragma(.cipherPageSize, to: pageSize) - try handle.setCipher(key: key) - try handle.exec(statementPragmaPageSize) - }) - } else { - handlePool.setConfig(named: DefaultConfigOrder.cipher.description, with: { (_) in }) - } - } - - public typealias PerformanceTracer = Handle.PerformanceTracer - public typealias SQLTracer = Handle.SQLTracer - - static private var performanceTracer = Atomic() - static private var sqlTracer = Atomic() - - /// You can register a tracer to monitor the performance of all SQLs. - /// It returns - /// 1. The collection of SQLs and the executions count of each SQL. - /// 2. Time consuming in nanoseconds. - /// 3. Tag of database. - /// - /// Note that: - /// 1. You should register trace before all db operations. - /// 2. Global tracer will be recovered by db tracer. - /// - /// Database.globalTrace(ofPerformance: { (tag, sqls, cost) in - /// if let wrappedTag = tag { - /// print("Tag: \(wrappedTag) ") - /// }else { - /// print("Nil tag") - /// } - /// sqls.forEach({ (arg) in - /// print("SQL: \(arg.key) Count: \(arg.value)") - /// }) - /// print("Total cost \(cost) nanoseconds") - /// }) - /// - /// Tracer may cause wcdb performance degradation, according to your needs to choose whether to open. - /// - /// - Parameter trace: trace. Nil to disable global preformance trace. - public static func globalTrace(ofPerformance trace: @escaping PerformanceTracer) { - performanceTracer.assign(trace) - } - public static func globalTrace(ofPerformance: Void?) { - performanceTracer.assign(nil) - } - - /// You can register a tracer to monitor the execution of all SQLs. - /// It returns a prepared or executed SQL. - /// Note that you should register trace before all db operations. - /// - /// Database.globalTrace(ofSQL: { (sql) in - /// print("SQL: \(sql)") - /// }) - /// - /// Tracer may cause wcdb performance degradation, according to your needs to choose whether to open. - /// - /// - Parameter trace: trace. Nil to disable global sql trace. - public static func globalTrace(ofSQL trace: @escaping SQLTracer) { - sqlTracer.assign(trace) - } - public static func globalTrace(ofSQL: Void?) { - sqlTracer.assign(nil) - } - - /// You can register a reporter to monitor all errors. - /// - /// Database.globalTrace(ofError: { (error) in - /// switch error.type { - /// case .sqliteGlobal: - /// debugPrint("[WCDB][DEBUG] \(error.description)") - /// case .warning: - /// print("[WCDB][WARNING] \(error.description)") - /// default: - /// print("[WCDB][ERROR] \(error.description)") - /// } - /// }) - /// - /// - Parameter errorReporter: report - public static func globalTrace(ofError errorReporter: @escaping Error.Reporter) { - Error.setReporter(errorReporter) - } - public static func globalTrace(ofError: Void?) { - Error.setReporter(nil) - } - /// Reset global error trace to default trace. - public static func resetGlobalTraceOfError() { - Error.resetReporter() - } - - private static let subthreadCheckpointDelay: TimeInterval = 2 - private static let subthreadCheckpointPages: Int = 1000 - private static let timedQueue = TimedQueue(withDelay: subthreadCheckpointDelay) - - private static let defaultConfigs: Configs = Configs(ContiguousArray(arrayLiteral: - Configs.Config(named: DefaultConfigOrder.fileProtection.description, with: { (handle: Handle) throws in - #if WCDB_IOS - try Handle.subfixs.forEach { - try File.addFirstUserAuthenticationFileProtection(atPath: handle.path+$0) - } - #endif //WCDB_IOS - }, orderBy: DefaultConfigOrder.fileProtection.rawValue), - Configs.Config(named: DefaultConfigOrder.trace.description, with: { (handle: Handle) throws in - if let sqlTracer = Database.sqlTracer.raw { - handle.trace(sql: sqlTracer) - } - if let performanceTracer = Database.performanceTracer.raw { - handle.trace(performance: performanceTracer) - } - }, orderBy: DefaultConfigOrder.trace.rawValue), - Configs.Config(emptyConfigNamed: DefaultConfigOrder.cipher.description, - orderBy: DefaultConfigOrder.cipher.rawValue), - Configs.Config(named: DefaultConfigOrder.basic.description, with: { (handle: Handle) throws in - guard !handle.isReadonly else { - let handleStatement = try handle.prepare(CommonStatement.getJournalMode) - try handleStatement.step() - let journalMode: String = handleStatement.columnValue(atIndex: 0) - try handleStatement.finalize() - assert(journalMode.caseInsensitiveCompare("WAL") == ComparisonResult.orderedSame, - "It is not possible to open read-only WAL databases.") - return - } - //Locking Mode - do { - //Get Locking Mode - let handleStatement = try handle.prepare(CommonStatement.getLockingMode) - try handleStatement.step() - let lockingMode: String = handleStatement.columnValue(atIndex: 0) - try handleStatement.finalize() - //Set Locking Mode - if lockingMode.caseInsensitiveCompare("NORMAL") != ComparisonResult.orderedSame { - try handle.exec(CommonStatement.enableLockingModeNormal) - } - } - //Synchronous - do { - try handle.exec(CommonStatement.enableSynchronousNormal) - } - //Journal Mode - do { - //Get Journal Mode - let handleStatement = try handle.prepare(CommonStatement.getJournalMode) - try handleStatement.step() - let journalMode: String = handleStatement.columnValue(atIndex: 0) - try handleStatement.finalize() - //Set Journal Mode - if journalMode.caseInsensitiveCompare("WAL") != ComparisonResult.orderedSame { - try handle.exec(CommonStatement.enableJournalModeWAL) - } - } - //Fullfsync - do { - try handle.exec(CommonStatement.enableFullfsync) - } - }, orderBy: DefaultConfigOrder.basic.rawValue), - Configs.Config(emptyConfigNamed: DefaultConfigOrder.synchronous.description, - orderBy: DefaultConfigOrder.synchronous.rawValue), - Configs.Config(named: DefaultConfigOrder.checkpoint.description, with: { (handle: Handle) throws in - handle.register(onCommitted: { (handle, pages, _) in - guard pages > subthreadCheckpointPages else { - return - } - DispatchQueue.once(name: "com.Tencent.WCDB.swift.checkpoint", { - DispatchQueue(label: "com.Tencent.WCDB.swift.checkpoint").async { - while true { - Database.timedQueue.wait(untilExpired: { - try? Database(withExistingPath: $0).exec(CommonStatement.checkpoint) - }) - } - } - }) - Database.timedQueue.reQueue(with: handle.path) - }) - }, orderBy: DefaultConfigOrder.checkpoint.rawValue), - Configs.Config(emptyConfigNamed: DefaultConfigOrder.tokenize.description, - orderBy: DefaultConfigOrder.tokenize.rawValue) - )) - - /// Default config order - public enum DefaultConfigOrder: Int, CustomStringConvertible { - case fileProtection = 0 - case trace = 1 - case cipher = 2 - case basic = 3 - case synchronous = 4 - case checkpoint = 5 - case tokenize = 6 - - public var description: String { - switch self { - case .fileProtection: - return "fileProtection" - case .trace: - return "trace" - case .cipher: - return "cipher" - case .basic: - return "basic" - case .synchronous: - return "synchronous" - case .checkpoint: - return "checkpoint" - case .tokenize: - return "tokenize" - } - } - } - - public typealias Config = HandlePool.Config - public typealias ConfigOrder = HandlePool.ConfigOrder - - /// Set config for this database. - /// - /// Since WCDB is a multi-handle database, an executing handle will not apply this config immediately. - /// Instead, all handles will run this config before its next operation. - /// - /// database.setConfig(named: "demo", with: { (handle: Handle) throws in - /// try handle.exec(StatementPragma().pragma(.secureDelete, to: true)) - /// }, orderBy: 1) - /// - /// - Parameters: - /// - name: The Identifier for this config - /// - callback: config - /// - order: The smaller number is called first - public func setConfig(named name: String, with callback: @escaping Config, orderBy order: ConfigOrder) { - handlePool.setConfig(named: name, with: callback, orderBy: order) - } - - /// This interface is equivalent to `database.setConfig(named: name, with: callback, orederBy: Int.max)`. - /// - /// - Parameters: - /// - name: The Identifier for this config - /// - callback: config - public func setConfig(named name: String, with callback: @escaping Config) { - handlePool.setConfig(named: name, with: callback) - } - - /// Set Synchronous for this database. It will disable checkpoint opti to avoid performance degradation. - /// Synchronous can improve the stability of the database and reduce database damage, - /// but there will be performance degradation. - /// - /// - Parameter isFull: enable or disable full synchronous - public func setSynchronous(isFull: Bool) { - if isFull { - handlePool.setConfig(named: DefaultConfigOrder.synchronous.description, with: { (handle: Handle) throws in - try handle.exec(CommonStatement.enableSynchronousFull) - }) - handlePool.setConfig(named: DefaultConfigOrder.checkpoint.description, with: { (handle: Handle) throws in - }) - } else { - handlePool.setConfig(named: DefaultConfigOrder.synchronous.description, with: { (handle: Handle) throws in - }) - let checkpointConfig = Database.defaultConfigs.config( - by: DefaultConfigOrder.checkpoint.description) - assert(checkpointConfig != nil, - "It should not be failed. If you think it's a bug, please report an issue to us.") - handlePool.setConfig(named: DefaultConfigOrder.checkpoint.description, - with: checkpointConfig!) - } - } - - /// This interface is equivalent to `database.setTokenizes(tokenizes)` - /// - /// - Parameter tokenizes: registed tokenizeName. You can use builtin tokenizer named `.WCDB` or `.Apple` - public func setTokenizes(_ tokenizes: Tokenize...) { - setTokenizes(tokenizes) - } - - /// Setup multiple tokenizers with names for current database. - /// - /// - Parameter tokenizes: registed tokenizeName. You can use builtin tokenizer named .WCDB or .Apple - public func setTokenizes(_ tokenizes: [Tokenize]) { - handlePool.setConfig(named: DefaultConfigOrder.tokenize.description) { (handle: Handle) throws in - try tokenizes.forEach({ (tokenize) in - let module = tokenize.module - let handleStatement = try handle.prepare(CommonStatement.fts3Tokenizer) - handleStatement.bind(module.name, toIndex: 1) - handleStatement.bind(module.address, toIndex: 2) - try handleStatement.step() - try handleStatement.finalize() - }) - } - } -} - -//Transaction -extension Database { - /// Generation a `Transaction` object to do a transaction. - /// - /// - Returns: Transaction - /// - Throws: `Error` - public func getTransaction() throws -> Transaction { - return Transaction(with: recyclableHandlePool, and: try flowOut()) - } -} - -//Table -extension Database { - /// Get a wrapper from an existing table. - /// - /// - Parameters: - /// - name: The name of the table. - /// - type: A class conform to TableCodable protocol. - /// - Returns: Nil for a non-existent table. - /// - Throws: `Error` - public func getTable( - named name: String, - of type: Root.Type = Root.self) throws -> Table? { - guard try isTableExists(name) else { - return nil - } - return Table(withDatabase: self, named: name) - } -} - -//File -extension Database { - /// Subfix of paths to all database-related files. - public static var subfixs: [String] { - return Handle.subfixs - } - - /// URLs to all database-related files. - public var urls: [URL] { - return paths.map({ (path) -> URL in - return URL(fileURLWithPath: path) - }) - } - - /// Paths to all database-related files. - public var paths: [String] { - return Database.subfixs.map({ (subfix) -> String in - return path+subfix - }) - } - - /// Remove all database-related files. - /// You should call it on a closed database. Otherwise you will get a warning. - /// - /// - Throws: `Error` - public func removeFiles() throws { - if !isBlockaded || isOpened { - Error.warning("Removing files on an opened database may cause unknown results") - } - try File.remove(files: paths) - } - - /// This interface is equivalent `moveFiles(toDirectory:withExtraFiles:)` - /// - /// - Parameters: - /// - directory: destination - /// - extraFiles: extraFiles - /// - Throws: `Error` - public func moveFiles(toDirectory directory: String, withExtraFiles extraFiles: String...) throws { - try moveFiles(toDirectory: directory, withExtraFiles: extraFiles) - } - - /// Move all database-related files and some extra files to directory safely. - /// You should call it on a closed database. Otherwise you will get a warning and you may get a corrupted database. - /// - /// - Parameters: - /// - directory: destination - /// - extraFiles: extraFiles - /// - Throws: `Error` - public func moveFiles(toDirectory directory: String, withExtraFiles extraFiles: [String]) throws { - try File.createDirectoryWithIntermediateDirectories(atPath: directory) - var recovers: [String] = [] - let paths = self.paths + extraFiles - do { - try paths.forEach({ (path) in - guard File.isExists(atPath: path) else { - return - } - let file = path.lastPathComponent - let newPaths = directory.stringByAppending(pathComponent: file) - if File.isExists(atPath: newPaths) { - try File.remove(files: [newPaths]) - } - try File.hardlink(atPath: path, toPath: newPaths) - recovers.append(newPaths) - }) - } catch let error { - try? File.remove(files: recovers) - throw error - } - try? File.remove(files: paths) - } - - /// Get the space used by the database files. - /// You should call it on a closed database. Otherwise you will get a warning. - /// - /// - Returns: The sum of files size in bytes. - /// - Throws: `Error` - public func getFilesSize() throws -> UInt64 { - if !isBlockaded || isOpened { - Error.warning("Getting files size on an opened database may get incorrect results") - } - return try File.getSize(ofFiles: paths) - } -} - -//Repair -extension Database { - /// Backup metadata to recover. - /// Since metadata will be changed while a table or an index is created or dropped, - /// you should call this periodically. - /// - /// - Parameter key: The cipher key for backup. Nil for non-encrypted. - /// - Throws: `Error` - public func backup(withKey key: Data? = nil) throws { - let handle = try flowOut() - try handle.raw.handle.backup(withKey: key) - } - - /// Recover data from a corruped db. You'd better to recover a closed database. - /// - /// - Parameters: - /// - source: The path to the corrupted database - /// - pageSize: Page size of the corrupted database. It's default to 4096 on iOS. - /// Page size never change unless you can call "PRAGMA page_size=NewPageSize" to set it. - /// Also, you can call "PRAGMA page_size" to check the current value while database is not corrupted. - /// - databaseKey: The cipher key for corrupeted database - /// - backupKey: The cipher key for backup - /// - Throws: `Error` - public func recover(fromPath source: String, - withPageSize pageSize: Int32 = 4096, - databaseKey: Data? = nil, - backupKey: Data? = nil) throws { - let handle = try flowOut() - try handle.raw.handle.recover(fromPath: source, - withPageSize: pageSize, - databaseKey: databaseKey, - backupKey: backupKey) - } -} - -extension Database: InsertChainCallInterface {} -extension Database: UpdateChainCallInterface {} -extension Database: DeleteChainCallInterface {} -extension Database: RowSelectChainCallInterface {} -extension Database: SelectChainCallInterface {} -extension Database: MultiSelectChainCallInterface {} - -extension Database: InsertInterface {} -extension Database: UpdateInterface {} -extension Database: DeleteInterface {} -extension Database: RowSelectInterface {} -extension Database: SelectInterface {} -extension Database: TableInterface {} diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/HandlePool.swift b/Example/Pods/WCDB.swift/swift/source/core/base/HandlePool.swift deleted file mode 100644 index c4aa9de6..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/HandlePool.swift +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class HandlePool { - private class Wrap { - let handlePool: HandlePool - var reference: Int = 0 - init(_ handlePool: HandlePool) { - self.handlePool = handlePool - } - } - - private static let spin = Spin() - private static var pools: [String: Wrap] = [:] - - static func getPool(withPath path: String, defaultConfigs: Configs) -> RecyclableHandlePool { - spin.lock(); defer { spin.unlock() } - var index = pools.index(forKey: path) - if index == nil { - let handlePool = HandlePool(withPath: path, defaultConfigs: defaultConfigs) - pools[path] = Wrap(handlePool) - index = pools.index(forKey: path) - } - return getExistingPool(atIndex: index!) - } - - static func getExistingPool(with tag: Tag) throws -> RecyclableHandlePool { - spin.lock(); defer { spin.unlock() } - guard let index = pools.firstIndex(where: { (arg) -> Bool in - return arg.value.handlePool.tag == tag - }) else { - throw Error.reportCore(tag: tag, - path: "", - operation: .getPool, - code: .misuse, - message: "Database with tag: \(tag) is not exists.") - } - return getExistingPool(atIndex: index) - } - - static func getExistingPool(withPath path: String) throws -> RecyclableHandlePool { - spin.lock(); defer { spin.unlock() } - guard let index = pools.index(forKey: path) else { - throw Error.reportCore(tag: nil, - path: path, - operation: .getPool, - code: .misuse, - message: "Database at path: \(path) is not exists.") - } - return getExistingPool(atIndex: index) - } - - private static func getExistingPool(atIndex index: Dictionary.Index) -> RecyclableHandlePool { - let node = pools[index] - let path = node.key - let wrap = node.value - wrap.reference += 1 - return Recyclable(wrap.handlePool, onRecycled: { - spin.lock(); defer { spin.unlock() } - let wrap = pools[path]! - wrap.reference -= 1 - if wrap.reference == 0 { - pools.removeValue(forKey: path) - } - }) - } - - typealias HandleWrap = (handle: Handle, configs: Configs) - private let handles = ConcurrentList(withCapacityCap: maxHardwareConcurrency) - - var tag: Tag? - let path: String - private let rwlock = RWLock() - private let aliveHandleCount = Atomic(0) - private var configs: Configs - - private init(withPath path: String, defaultConfigs: Configs) { - self.path = path - self.configs = defaultConfigs - } - - var isDrained: Bool { - return aliveHandleCount == 0 - } - - func fillOne() throws { - rwlock.lockRead(); defer { rwlock.unlockRead() } - let handle = try generate() - if handles.pushBack(handle) { - aliveHandleCount += 1 - } - } - - private func invoke(handleWrap: inout HandleWrap) throws { - let newConfigs = self.configs - if newConfigs != handleWrap.configs { - try newConfigs.invoke(handle: handleWrap.handle) - handleWrap.configs = newConfigs - } - } - - static private let maxConcurrency = max(maxHardwareConcurrency, 64) - static private let maxHardwareConcurrency = ProcessInfo.processInfo.processorCount - - func flowOut() throws -> RecyclableHandle { - var unlock = true - rwlock.lockRead(); defer { if unlock { rwlock.unlockRead() } } - var handleWrap = handles.popBack() - if handleWrap == nil { - guard aliveHandleCount < HandlePool.maxConcurrency else { - throw Error.reportCore(tag: tag, - path: path, - operation: .flowOut, - code: .exceed, - message: "The concurrency of database exceeds the max concurrency") - } - handleWrap = try generate() - aliveHandleCount += 1 - if aliveHandleCount > HandlePool.maxHardwareConcurrency { - var warning = "The concurrency of database: \(tag ?? 0) with \(aliveHandleCount)" - warning.append(" exceeds the concurrency of hardware: \(HandlePool.maxHardwareConcurrency)") - Error.warning(warning) - } - } - handleWrap!.handle.tag = self.tag - try invoke(handleWrap: &handleWrap!) - unlock = false - return RecyclableHandle(handleWrap!, onRecycled: { - self.flowBack(handleWrap!) - }) - } - - private func flowBack(_ handleWrap: HandleWrap) { - let inserted = handles.pushBack(handleWrap) - rwlock.unlockRead() - if !inserted { - aliveHandleCount -= 1 - } - } - - private func generate() throws -> HandleWrap { - let handle = Handle(withPath: path) - handle.tag = tag - let configs = self.configs - try handle.open() - try configs.invoke(handle: handle) - return HandleWrap(handle: handle, configs: configs) - } - - func blockade() { - rwlock.lockWrite() - } - - func unblockade() { - rwlock.unlockWrite() - } - - var isBlockaded: Bool { - return rwlock.isWriting - } - - public typealias OnDrained = () throws -> Void - - func drain(onDrained: OnDrained) rethrows { - blockade(); defer { unblockade() } - let size = handles.clear() - aliveHandleCount -= size - try onDrained() - } - - func drain() { - blockade(); defer { unblockade() } - let size = handles.clear() - aliveHandleCount -= size - } - - func purgeFreeHandles() { - rwlock.lockRead(); defer { rwlock.unlockRead() } - let size = handles.clear() - aliveHandleCount -= size - } - - public typealias Config = Configs.Callback - public typealias ConfigOrder = Configs.Order - - func setConfig(named name: String, with callback: @escaping Config, orderBy order: ConfigOrder) { - configs.setConfig(named: name, with: callback, orderBy: order) - } - - func setConfig(named name: String, with callback: @escaping Config) { - configs.setConfig(named: name, with: callback) - } - - static func purgeFreeHandlesInAllPools() { - let handlePools: [HandlePool]! - do { - spin.lock(); defer { spin.unlock() } - handlePools = pools.values.reduce(into: []) { $0.append($1.handlePool) } - } - handlePools.forEach { $0.purgeFreeHandles() } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/RecyclableCore.swift b/Example/Pods/WCDB.swift/swift/source/core/base/RecyclableCore.swift deleted file mode 100644 index 11dc0041..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/RecyclableCore.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -typealias RecyclableHandlePool = Recyclable - -final class RecyclableHandleStatement: Recyclable { - private let recyclableHandle: RecyclableHandle - - init(recyclableHandle: RecyclableHandle, - handleStatement: HandleStatement) { - self.recyclableHandle = recyclableHandle - super.init(handleStatement) - } -} - -typealias RecyclableHandle = Recyclable diff --git a/Example/Pods/WCDB.swift/swift/source/core/base/Transaction.swift b/Example/Pods/WCDB.swift/swift/source/core/base/Transaction.swift deleted file mode 100644 index 5adfb526..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/base/Transaction.swift +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Thread-safe Transaction object -public final class Transaction: Core { - private let recyclableHandle: RecyclableHandle - /// Check whether is already in transaction. - public private(set) var isInTransaction: Bool = false - private var mutex: RecursiveMutex = RecursiveMutex() - - init(with recyclableHandlePool: RecyclableHandlePool, and recyclableHandle: RecyclableHandle) { - self.recyclableHandle = recyclableHandle - super.init(with: recyclableHandlePool) - } - - deinit { - if isInTransaction { - try? rollback() - } - } - - private var handle: Handle { - return recyclableHandle.raw.handle - } - - override func prepare(_ statement: Statement) throws -> RecyclableHandleStatement { - mutex.lock(); defer { mutex.unlock() } - return try prepare(statement, in: recyclableHandle) - } - - /// Exec a specific sql. - /// Note that you can use this interface to execute a SQL that is not contained in the WCDB interface layer. - /// - /// - Parameter statement: WINQ statement - /// - Throws: `Error` - public override func exec(_ statement: Statement) throws { - mutex.lock(); defer { mutex.unlock() } - try exec(statement, in: recyclableHandle) - } - - /// Prepare a specific sql. - /// Note that you can use this interface to prepare a SQL that is not contained in the WCDB interface layer - /// - /// - Parameter statement: WINQ statement - /// - Returns: CoreStatement - /// - Throws: `Error` - public override func prepare(_ statement: Statement) throws -> CoreStatement { - mutex.lock(); defer { mutex.unlock() } - return try super.prepare(statement) - } - - /// Check whether table exists - /// - /// - Parameter table: The name of the table to be checked. - /// - Returns: True if table exists. False if table does not exist. - /// - Throws: `Error` - public override func isTableExists(_ table: String) throws -> Bool { - mutex.lock(); defer { mutex.unlock() } - return try super.isTableExists(table) - } - - /// Run a transaction in closure - /// - /// try transaction.run(transaction: { () throws -> Void in - /// try transaction.insert(objects: objects, intoTable: table) - /// }) - /// - /// - Parameter transaction: Operation inside transaction - /// - Throws: `Error` - public override func run(transaction: TransactionClosure) throws { - mutex.lock(); defer { mutex.unlock() } - try super.run(transaction: transaction) - } - - /// Run a controllable transaction in closure - /// - /// try transaction.run(controllableTransaction: { () throws -> Bool in - /// try transaction.insert(objects: objects, intoTable: table) - /// return true // return true to commit transaction and return false to rollback transaction. - /// }) - /// - /// - Parameter controllableTransaction: Operation inside transaction - /// - Throws: `Error` - public override func run(controllableTransaction: ControlableTransactionClosure) throws { - mutex.lock(); defer { mutex.unlock() } - try super.run(controllableTransaction: controllableTransaction) - } - - /// Separate interface of `run(transaction:)` - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// - Throws: `Error` - public override func begin(_ mode: StatementTransaction.Mode = .immediate) throws { - mutex.lock(); defer { mutex.unlock() } - let statement = mode == .immediate ? - CommonStatement.beginTransactionImmediate : - StatementTransaction().begin(mode) - try handle.exec(statement) - isInTransaction = true - } - - /// Separate interface of `run(transaction:)` - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// - Throws: `Error` - public override func commit() throws { - mutex.lock(); defer { mutex.unlock() } - try handle.exec(CommonStatement.commitTransaction) - isInTransaction = false - } - - /// Separate interface of run(transaction:) - /// You should call `begin`, `commit`, `rollback` and all other operations in same thread. - /// - Throws: `Error` - public override func rollback() throws { - mutex.lock(); defer { mutex.unlock() } - isInTransaction = false - try handle.exec(CommonStatement.rollbackTransaction) - } - - /// Run a embedded transaction in closure - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// try transaction.run(embeddedTransaction: { () throws -> Void in - /// try transaction.insert(objects: objects, intoTable: table) - /// }) - /// - /// - Parameter embeddedTransaction: Operation inside transaction - /// - Throws: `Error` - public override func run(embeddedTransaction: TransactionClosure) throws { - mutex.lock(); defer { mutex.unlock() } - if isInTransaction { - return try embeddedTransaction() - } - return try run(transaction: embeddedTransaction) - } - - /// The number of changed rows in the most recent call. - /// It should be called after executing successfully - public var changes: Int { - mutex.lock(); defer { mutex.unlock() } - return handle.changes - } -} - -extension Transaction: InsertChainCallInterface {} -extension Transaction: UpdateChainCallInterface {} -extension Transaction: DeleteChainCallInterface {} -extension Transaction: RowSelectChainCallInterface {} -extension Transaction: SelectChainCallInterface {} -extension Transaction: MultiSelectChainCallInterface {} - -extension Transaction: InsertInterface {} -extension Transaction: UpdateInterface {} -extension Transaction: DeleteInterface {} -extension Transaction: RowSelectInterface {} -extension Transaction: SelectInterface {} -extension Transaction: TableInterface {} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/ColumnConstraintBinding.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/ColumnConstraintBinding.swift deleted file mode 100644 index 5969b8ff..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/ColumnConstraintBinding.swift +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct ColumnConstraintBinding { - let isPrimary: Bool - let isAutoIncrement: Bool - let defaultValue: ColumnDef.DefaultType? - let conflict: Conflict? - let isNotNull: Bool - let isUnique: Bool - let term: OrderTerm? - - public init(isPrimary: Bool = false, - orderBy term: OrderTerm? = nil, - isAutoIncrement: Bool = false, - onConflict conflict: Conflict? = nil, - isNotNull: Bool = false, - isUnique: Bool = false, - defaultTo defaultValue: ColumnDef.DefaultType? = nil) { - self.isPrimary = isPrimary - self.isAutoIncrement = isAutoIncrement - self.isNotNull = isNotNull - self.isUnique = isUnique - self.defaultValue = defaultValue - self.term = term - self.conflict = conflict - } - - public init( - isPrimary: Bool = false, - orderBy term: OrderTerm? = nil, - isAutoIncrement: Bool = false, - onConflict conflict: Conflict? = nil, - isNotNull: Bool = false, - isUnique: Bool = false, - defaultTo defaultEncodedValue: T) { - var defaultValue: ColumnDef.DefaultType! - let value = defaultEncodedValue.archivedValue() - switch T.columnType { - case .integer32: - defaultValue = .int32(value.int32Value) - case .integer64: - defaultValue = .int64(value.int64Value) - case .text: - defaultValue = .text(value.stringValue) - case .float: - defaultValue = .float(value.doubleValue) - case .BLOB: - defaultValue = .BLOB(value.dataValue) - case .null: - defaultValue = .null - } - self.init(isPrimary: isPrimary, - orderBy: term, - isAutoIncrement: isAutoIncrement, - onConflict: conflict, - isNotNull: isNotNull, - isUnique: isUnique, - defaultTo: defaultValue) - } - - func generateColumnDef(with rawColumnDef: ColumnDef) -> ColumnDef { - let columnDef = rawColumnDef - if isPrimary { - columnDef.makePrimary(orderBy: term, isAutoIncrement: isAutoIncrement, onConflict: conflict) - } - if isNotNull { - columnDef.makeNotNull() - } - if isUnique { - columnDef.makeUnique() - } - if defaultValue != nil { - columnDef.makeDefault(to: defaultValue!) - } - return columnDef - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/IndexBinding.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/IndexBinding.swift deleted file mode 100644 index 5a25f579..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/IndexBinding.swift +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -public struct IndexBinding { - public typealias Subfix = String - - let columnIndexes: [ColumnIndex] - let isUnique: Bool - - public init(isUnique: Bool = false, indexesBy columnIndexConvertibleList: [ColumnIndexConvertible]) { - self.columnIndexes = columnIndexConvertibleList.asIndexes() - self.isUnique = isUnique - } - - public init(isUnique: Bool = false, - indexesBy columnIndexConvertibleList: ColumnIndexConvertible...) { - self.init(isUnique: isUnique, indexesBy: columnIndexConvertibleList) - } - - func generateCreateIndexStatement(onTable tableName: String, - withIndexSubfix indexSubfix: String) -> StatementCreateIndex { - return StatementCreateIndex() - .create(index: tableName+indexSubfix, - isUnique: isUnique, - ifNotExists: true) - .on(table: tableName, - indexesBy: columnIndexes) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/Property.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/Property.swift deleted file mode 100644 index c90ad981..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/Property.swift +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol PropertyConvertible: ColumnConvertible, PropertyRedirectable { - var codingTableKey: CodingTableKeyBase {get} - - func asProperty() -> Property - - func `in`(table: String) -> Property -} - -public typealias PropertyOperable = PropertyConvertible & ExpressionOperable - -public final class Property: Describable { - public private(set) var description: String - public private(set) var codingTableKey: CodingTableKeyBase - - public init(named name: String, with codingTableKey: CodingTableKeyBase) { - self.codingTableKey = codingTableKey - self.description = name - } - - public init(with codingTableKey: CodingTableKeyBase) { - self.codingTableKey = codingTableKey - self.description = codingTableKey.stringValue - } - - public var name: String { - return description - } -} - -extension Property: PropertyOperable { - public func asProperty() -> Property { - return self - } - - public func `in`(table: String) -> Property { - let column: Column = self.in(table: table) - return Property(named: column.description, with: codingTableKey) - } - - public func asColumn() -> Column { - return Column(named: name) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/Redirectable.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/Redirectable.swift deleted file mode 100644 index e5e42653..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/Redirectable.swift +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol PropertyRedirectable { - func `as`(_ propertyConvertible: PropertyConvertible) -> Property -} - -extension PropertyRedirectable where Self: Describable { - public func `as`(_ propertyConvertible: PropertyConvertible) -> Property { - return Property(named: description, with: propertyConvertible.codingTableKey) - } -} - -extension Column: PropertyRedirectable {} - -extension ColumnResult: PropertyRedirectable {} - -extension Expression: PropertyRedirectable {} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/TableBinding.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/TableBinding.swift deleted file mode 100644 index 607fd601..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/TableBinding.swift +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class TableBinding { - private let properties: [CodingTableKeyType: Property] - let allProperties: [Property] - let allKeys: [CodingTableKeyType] - - private lazy var columnTypes: [String: ColumnType] = { - // CodingTableKeyType.Root must conform to TableEncodable protocol. - let tableDecodableType = CodingTableKeyType.Root.self as! TableDecodableBase.Type - return ColumnTypeDecoder.types(of: tableDecodableType) - }() - - private lazy var allColumnDef: [ColumnDef] = allKeys.map { (key) -> ColumnDef in - return generateColumnDef(with: key) - } - - private typealias ColumnConstraintBindingMap = [CodingTableKeyType: ColumnConstraintBinding] - private lazy var columnConstraintBindings: ColumnConstraintBindingMap? = CodingTableKeyType.columnConstraintBindings - - private typealias IndexBindingMap = [IndexBinding.Subfix: IndexBinding] - private lazy var indexBindings: IndexBindingMap? = CodingTableKeyType.indexBindings - - private typealias TableConstraintBindingMap = [TableConstraintBinding.Name: TableConstraintBinding] - private lazy var tableConstraintBindings: TableConstraintBindingMap? = CodingTableKeyType.tableConstraintBindings - private lazy var virtualTableBinding: VirtualTableBinding? = CodingTableKeyType.virtualTableBinding - - private lazy var primaryKey: CodingTableKeyType? = { - guard let filtered = columnConstraintBindings?.filter({ (args) -> Bool in - return args.value.isPrimary - }) else { - return nil - } - guard filtered.count == 1 else { - assert(filtered.count == 0, "Only one primary key is supported. Use MultiPrimaryBinding instead") - return nil - } - return filtered.first!.key - }() - - public init(_ type: CodingTableKeyType.Type) { - var allProperties: [Property] = [] - var properties: [CodingTableKeyType: Property] = [:] - var allKeys: [CodingTableKeyType] = [] - - var i = 0 - while true { - guard let key = (withUnsafePointer(to: &i) { - return $0.withMemoryRebound(to: CodingTableKeyType?.self, capacity: 1, { return $0.pointee }) - }) else { - break - } - allKeys.append(key) - i += 1 - } - - for key in allKeys { - let property = Property(with: key) - properties[key] = property - allProperties.append(property) - } - - self.allKeys = allKeys - self.properties = properties - self.allProperties = allProperties - - #if DEBUG - if let tableDecodableType = CodingTableKeyType.Root.self as? TableDecodableBase.Type { - let types = ColumnTypeDecoder.types(of: tableDecodableType) - let keys = allKeys.filter({ (key) -> Bool in - return types.index(forKey: key.stringValue) == nil - }) - assert(keys.count == 0, - """ - The following keys: \(keys) can't be decoded. \ - 1. Try to change their definition from `let` to `var` or report an issue to us. \ - 2. Try to rename the `static` variable with same name. - """) - } - #endif - } - - typealias TypedCodingTableKeyType = CodingTableKeyType - func property(from codingTableKey: CodingTableKeyType) -> Property { - let typedCodingTableKey = codingTableKey as? TypedCodingTableKeyType - assert(typedCodingTableKey != nil, "[\(codingTableKey)] must conform to CodingTableKey protocol.") - let typedProperty = properties[typedCodingTableKey!] - assert(typedProperty != nil, "It should not be failed. If you think it's a bug, please report an issue to us.") - return typedProperty! - } - - func generateColumnDef(with key: CodingTableKeyBase) -> ColumnDef { - let codingTableKey = key as? CodingTableKeyType - assert(codingTableKey != nil, "[\(key)] must conform to CodingTableKey protocol.") - let columnType = columnTypes[codingTableKey!.stringValue] - assert(columnType != nil, "It should not be failed. If you think it's a bug, please report an issue to us.") - var columnDef = ColumnDef(with: codingTableKey!, and: columnType!) - if let index = columnConstraintBindings?.index(forKey: codingTableKey!) { - columnDef = columnConstraintBindings![index].value.generateColumnDef(with: columnDef) - } - return columnDef - } - - public func generateCreateVirtualTableStatement(named table: String) -> StatementCreateVirtualTable { - assert(virtualTableBinding != nil, "Virtual table binding is not defined") - let columnModuleArguments = allColumnDef.map { ModuleArgument(with: $0) } - let tableCostraintArguments = tableConstraintBindings?.map { (tableConstraintBinding) -> ModuleArgument in - let key = tableConstraintBinding.key - return ModuleArgument(with: tableConstraintBinding.value.generateConstraint(withName: key)) - } ?? [] - let arguments = columnModuleArguments + tableCostraintArguments + virtualTableBinding!.arguments - return StatementCreateVirtualTable() - .create(virtualTable: table) - .using(module: virtualTableBinding!.module, - arguments: arguments) - } - - public func generateCreateTableStatement(named table: String) -> StatementCreateTable { - let tableConstraints = tableConstraintBindings?.map { $0.value.generateConstraint(withName: $0.key) } - return StatementCreateTable().create(table: table, - with: allColumnDef, - and: tableConstraints) - } - - public func generateCreateIndexStatements(onTable table: String) -> [StatementCreateIndex]? { - guard let indexBindings = self.indexBindings else { - return nil - } - return indexBindings.map { $0.value.generateCreateIndexStatement(onTable: table, withIndexSubfix: $0.key)} - } - - func getPrimaryKey() -> CodingTableKeyBase? { - return primaryKey - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/TableConstraintBinding.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/TableConstraintBinding.swift deleted file mode 100644 index f2f4d34b..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/TableConstraintBinding.swift +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol TableConstraintBinding { - typealias Name = String - func generateConstraint(withName name: String) -> TableConstraint -} - -public struct MultiPrimaryBinding: TableConstraintBinding { - let conflict: Conflict? - let columnIndexConvertibleList: [ColumnIndexConvertible] - - public init(indexesBy columnIndexConvertibleList: ColumnIndexConvertible..., - onConflict conflict: Conflict? = nil) { - self.init(indexesBy: columnIndexConvertibleList, onConflict: conflict) - } - - public init(indexesBy columnIndexConvertibleList: [ColumnIndexConvertible], - onConflict conflict: Conflict? = nil) { - self.columnIndexConvertibleList = columnIndexConvertibleList - self.conflict = conflict - } - - public func generateConstraint(withName name: String) -> TableConstraint { - let tableConstraint = TableConstraint(named: name).makePrimary(indexesBy: columnIndexConvertibleList) - if let wrappedConflict = conflict { - tableConstraint.onConflict(wrappedConflict) - } - return tableConstraint - } -} - -public struct MultiUniqueBinding: TableConstraintBinding { - let conflict: Conflict? - let columnIndexConvertibleList: [ColumnIndexConvertible] - - public init(indexesBy columnIndexConvertibleList: ColumnIndexConvertible..., - onConflict conflict: Conflict? = nil) { - self.init(indexesBy: columnIndexConvertibleList, onConflict: conflict) - } - - public init(indexesBy columnIndexConvertibleList: [ColumnIndexConvertible], - onConflict conflict: Conflict? = nil) { - self.columnIndexConvertibleList = columnIndexConvertibleList - self.conflict = conflict - } - - public func generateConstraint(withName name: String) -> TableConstraint { - let tableConstraint = TableConstraint(named: name).makeUnique(indexesBy: columnIndexConvertibleList) - if let wrappedConflict = conflict { - tableConstraint.onConflict(wrappedConflict) - } - return tableConstraint - } -} - -public struct CheckBinding: TableConstraintBinding { - let condition: Expression - - public init(check condition: Expression) { - self.condition = condition - } - - public func generateConstraint(withName name: String) -> TableConstraint { - return TableConstraint(named: name).check(condition) - } -} - -public struct ForeignKeyBinding: TableConstraintBinding { - let columnConvertibleList: [ColumnConvertible] - let foreignKey: ForeignKey - - public init(_ columnConvertibleList: ColumnConvertible..., foreignKey: ForeignKey) { - self.init(columnConvertibleList, foreignKey: foreignKey) - } - - public init(_ columnConvertibleList: [ColumnConvertible], foreignKey: ForeignKey) { - self.columnConvertibleList = columnConvertibleList - self.foreignKey = foreignKey - } - - public func generateConstraint(withName name: String) -> TableConstraint { - return TableConstraint(named: name).makeForeignKey(columnConvertibleList, foreignKey: foreignKey) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/binding/VirtualTableBinding.swift b/Example/Pods/WCDB.swift/swift/source/core/binding/VirtualTableBinding.swift deleted file mode 100644 index 9373d8b9..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/binding/VirtualTableBinding.swift +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct VirtualTableBinding { - let arguments: [ModuleArgument] - let module: String - - public init(withModule module: String, and arguments: [ModuleArgument]) { - self.module = module - self.arguments = arguments - } - - public init(withModule module: String, and arguments: ModuleArgument...) { - self.init(withModule: module, and: arguments) - } - - public init(with module: FTSModule, and arguments: [ModuleArgument]) { - self.init(withModule: module.name, and: arguments) - } - - public init(with module: FTSModule, and arguments: ModuleArgument...) { - self.init(with: module, and: arguments) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/CodingTableKey.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/CodingTableKey.swift deleted file mode 100644 index cce0033d..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/CodingTableKey.swift +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol CodingTableKeyBase: CodingKey { - var rootType: TableCodableBase.Type {get} -} - -public protocol CodingTableKey: CodingTableKeyBase, - Hashable, - PropertyOperable, - RawRepresentable where RawValue == String { - associatedtype Root: TableCodableBase - - static var all: [Property] {get} - static var any: Column {get} - - static var objectRelationalMapping: TableBinding {get} - static var columnConstraintBindings: [Self: ColumnConstraintBinding]? {get} - static var indexBindings: [IndexBinding.Subfix: IndexBinding]? {get} - static var tableConstraintBindings: [TableConstraintBinding.Name: TableConstraintBinding]? {get} - static var virtualTableBinding: VirtualTableBinding? {get} -} - -extension CodingTableKey { - public var rootType: TableCodableBase.Type { - return Root.self - } -} - -extension CodingTableKey { - public static var all: [Property] { - return objectRelationalMapping.allProperties - } - public static var any: Column { - return Column.all - } -} - -extension CodingTableKey { - public static var columnConstraintBindings: [Self: ColumnConstraintBinding]? { - return nil - } - - public static var indexBindings: [IndexBinding.Subfix: IndexBinding]? { - return nil - } - - public static var tableConstraintBindings: [TableConstraintBinding.Name: TableConstraintBinding]? { - return nil - } - - public static var virtualTableBinding: VirtualTableBinding? { - return nil - } -} - -extension CodingTableKey { - public var codingTableKey: CodingTableKeyBase { - return self - } - - public func `as`(_ propertyConvertible: PropertyConvertible) -> Property { - return Property(named: stringValue, with: propertyConvertible.codingTableKey) - } - - public func asProperty() -> Property { - return Self.objectRelationalMapping.property(from: self) - } - - public func `in`(table: String) -> Property { - return asProperty().`in`(table: table) - } - - public func asExpression() -> Expression { - return asColumn().asExpression() - } - - public func asColumn() -> Column { - return Column(named: stringValue) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnCodable.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnCodable.swift deleted file mode 100644 index 964c990e..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnCodable.swift +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -// Column -public protocol ColumnCodableBase { - static var columnType: ColumnType {get} -} - -public protocol ColumnEncodable: Encodable, ColumnCodableBase { - func archivedValue() -> FundamentalValue -} -public extension ColumnEncodable where Self: LiteralValueConvertible { - func asLiteralValue() -> LiteralValue { - return LiteralValue(self) - } -} - -public protocol ColumnDecodable: Decodable, ColumnCodableBase { - init?(with value: FundamentalValue) -} - -public typealias ColumnCodable = ColumnEncodable & ColumnDecodable diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnTypeDecoder.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnTypeDecoder.swift deleted file mode 100644 index 74368027..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/ColumnTypeDecoder.swift +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class ColumnTypeDecoder: Decoder { - - private var results: [String: ColumnType] = [:] - - static func types(of type: TableDecodableBase.Type) -> [String: ColumnType] { - let decoder = ColumnTypeDecoder() - _ = try? type.init(from: decoder) - return decoder.results - } - - func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key: CodingKey { - return KeyedDecodingContainer(ColumnTypeDecodingContainer(with: self)) - } - - private final class ColumnTypeDecodingContainer: KeyedDecodingContainerProtocol { - - typealias Key = CodingKeys - - private let decoder: ColumnTypeDecoder - - private struct SizedPointer { - private let pointer: UnsafeMutableRawPointer - private let size: Int - init(of type: T.Type = T.self) { - size = MemoryLayout.size - pointer = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: 1) - memset(pointer, 0, size) - } - func deallocate() { - pointer.deallocate() - } - func getPointee(of type: T.Type = T.self) -> T { - return pointer.assumingMemoryBound(to: type).pointee - } - } - - private var sizedPointers: ContiguousArray - - init(with decoder: ColumnTypeDecoder) { - self.decoder = decoder - self.sizedPointers = ContiguousArray() - } - - deinit { - for sizedPointer in sizedPointers { - sizedPointer.deallocate() - } - } - - func contains(_ key: Key) -> Bool { - return true - } - - func decodeNil(forKey key: Key) throws -> Bool { - decoder.results[key.stringValue] = Bool.columnType - return false - } - - func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - decoder.results[key.stringValue] = type.columnType - return false - } - - func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - decoder.results[key.stringValue] = type.columnType - return 0 - } - - func decode(_ type: String.Type, forKey key: Key) throws -> String { - decoder.results[key.stringValue] = type.columnType - return "" - } - - func decode(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable { - // `type` must conform to ColumnDecodableBase protocol - let columnDecodableType = type as! ColumnDecodable.Type - decoder.results[key.stringValue] = columnDecodableType.columnType - - let sizedPointer = SizedPointer(of: T.self) - sizedPointers.append(sizedPointer) - return sizedPointer.getPointee() - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - var allKeys: [Key] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedContainer(keyedBy type: NestedKey.Type, - forKey key: Key) - throws -> KeyedDecodingContainer where NestedKey: CodingKey { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superDecoder() throws -> Decoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superDecoder(forKey key: Key) throws -> Decoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - var userInfo: [CodingUserInfoKey: Any] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func unkeyedContainer() throws -> UnkeyedDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func singleValueContainer() throws -> SingleValueDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/TableCodable.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/TableCodable.swift deleted file mode 100644 index 02cbcfb7..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/TableCodable.swift +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol TableCodableBase {} - -public protocol TableEncodableBase: Encodable, TableCodableBase {} - -public protocol TableEncodable: TableEncodableBase where CodingKeys.Root == Self { - associatedtype CodingKeys: CodingTableKey - typealias Properties = CodingKeys - - var isAutoIncrement: Bool {get} - var lastInsertedRowID: Int64 {get set} -} - -extension TableEncodable { - public var isAutoIncrement: Bool { - return false - } - - public var lastInsertedRowID: Int64 { - get { return Int64.min } - set { } - } -} - -public protocol TableDecodableBase: Decodable, TableCodableBase {} - -public protocol TableDecodable: TableDecodableBase where CodingKeys.Root == Self { - associatedtype CodingKeys: CodingTableKey - typealias Properties = CodingKeys -} - -public typealias TableCodable = TableEncodable & TableDecodable diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/TableDecoder.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/TableDecoder.swift deleted file mode 100644 index ff87e8ea..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/TableDecoder.swift +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class TableDecoder: Decoder { - - private let recyclableHandleStatement: RecyclableHandleStatement - - typealias HashedKey = [Int: Int] // hash value -> index - private let hashedKeys: HashedKey - - private var container: Any? - - init(_ codingTableKeys: [CodingTableKeyBase], on recyclableHandleStatement: RecyclableHandleStatement) { - var hashedKeys: HashedKey = [:] - for (index, key) in codingTableKeys.enumerated() { - hashedKeys[key.stringValue.hashValue] = index - } - self.hashedKeys = hashedKeys - self.recyclableHandleStatement = recyclableHandleStatement - } - - init(_ hashedKeys: HashedKey, on recyclableHandleStatement: RecyclableHandleStatement) { - self.hashedKeys = hashedKeys - self.recyclableHandleStatement = recyclableHandleStatement - } - - func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key: CodingKey { - if container == nil { - container = KeyedDecodingContainer(KeyedDecodingTableContainer(with: hashedKeys, - on: recyclableHandleStatement.raw)) - } - // It should not be failed. If you think it's a bug, please report an issue to us. - return container as! KeyedDecodingContainer - } - - private final class KeyedDecodingTableContainer : KeyedDecodingContainerProtocol { - typealias Key = CodingKeys - - private let handleStatement: HandleStatement - - private let hashedKeys: HashedKey - - init(with hashedKeys: HashedKey, on handleStatement: HandleStatement) { - self.handleStatement = handleStatement - self.hashedKeys = hashedKeys - } - - private func columnIndex(by key: Key) -> Int { - let index = hashedKeys[key.stringValue.hashValue] - assert(index != nil, "If [\(key)] would not be decoded, please make it optional.") - return index! - } - - private func columnIndexIfPresent(by key: Key) -> Int? { - return hashedKeys[key.stringValue.hashValue] - } - - func contains(_ key: Key) -> Bool { - return true - } - - //Decode - func decodeNil(forKey key: Key) throws -> Bool { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toBool() - } - - func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toBool() - } - - func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int64.self).toInt() - } - - func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toInt8() - } - - func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toInt16() - } - - func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index) - } - - func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index) - } - - func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int64.self).toUInt() - } - - func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt8() - } - - func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt16() - } - - func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt32() - } - - func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Int64.self).toUInt64() - } - - func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index, of: Double.self).toFloat() - } - - func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index) - } - - func decode(_ type: String.Type, forKey key: Key) throws -> String { - let index: Int = columnIndex(by: key) - return handleStatement.columnValue(atIndex: index) - } - - func decode(_ type: Object.Type, forKey key: Key) throws -> Object where Object: Decodable { - let index: Int = columnIndex(by: key) - //`key` must conform to ColumnDecodable protocol. - let decodableType = Object.self as! ColumnDecodable.Type - guard let wrappedDecoded = decodableType.init(with: handleStatement.columnValue(atIndex: index)) else { - throw Error.reportCore(tag: handleStatement.tag, - path: handleStatement.path, - operation: .encode, - code: .misuse, - message: "If [\(key)] would be decoded as nil, please make it optional.") - } - //It should not be failed. If you think it's a bug, please report an issue to us. - return wrappedDecoded as! Object - } - - //Decode if present - func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toBool() - } - - func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int64.self).toInt() - } - - func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toInt8() - } - - func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toInt16() - } - - func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index) - } - - func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index) - } - - func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int64.self).toUInt() - } - - func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt8() - } - - func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt16() - } - - func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int32.self).toUInt32() - } - - func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Int64.self).toUInt64() - } - - func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index, of: Double.self).toFloat() - } - - func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index) - } - - func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - return handleStatement.columnValue(atIndex: index) - } - - func decodeIfPresent(_ type: Object.Type, forKey key: Key) throws -> Object? where Object: Decodable { - guard let index = columnIndexIfPresent(by: key), handleStatement.columnType(atIndex: index) != .null else { - return nil - } - //`key` must conform to ColumnDecodable protocol. - let decodableType = Object.self as! ColumnDecodable.Type - guard let wrappedDecoded = decodableType.init(with: handleStatement.columnValue(atIndex: index)) else { - return nil - } - //It should not be failed. If you think it's a bug, please report an issue to us. - return (wrappedDecoded as! Object) - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - var allKeys: [Key] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedContainer(keyedBy type: NestedKey.Type, - forKey key: Key) throws -> KeyedDecodingContainer - where NestedKey: CodingKey { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superDecoder() throws -> Swift.Decoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superDecoder(forKey key: Key) throws -> Swift.Decoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - var userInfo: [CodingUserInfoKey: Any] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func unkeyedContainer() throws -> UnkeyedDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func singleValueContainer() throws -> SingleValueDecodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/codable/TableEncoder.swift b/Example/Pods/WCDB.swift/swift/source/core/codable/TableEncoder.swift deleted file mode 100644 index 36c7053e..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/codable/TableEncoder.swift +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class TableEncoder: Encoder { - - private var container: Any? - private var keyedPrimaryKeyEncodableTableContainer: KeyedPrimaryKeyEncodableTableContainer? - - private let recyclableHandleStatement: RecyclableHandleStatement - - typealias HashedKey = [Int: Int] // hash value -> index - private let hashedKeys: HashedKey - - var primaryKeyHash: Int? - var isPrimaryKeyEncoded = true - - init(_ codingTableKeys: [CodingTableKeyBase], - on recyclableHandleStatement: RecyclableHandleStatement) { - var hashedKeys: HashedKey = [:] - for (index, key) in codingTableKeys.enumerated() { - hashedKeys[key.stringValue.hashValue] = index + 1 - } - self.hashedKeys = hashedKeys - self.recyclableHandleStatement = recyclableHandleStatement - } - - init(_ hashedKeys: HashedKey, on recyclableHandleStatement: RecyclableHandleStatement) { - self.hashedKeys = hashedKeys - self.recyclableHandleStatement = recyclableHandleStatement - } - - func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key: CodingKey { - if container == nil { - let keyedContainer = KeyedEncodingTableContainer(with: hashedKeys, - on: recyclableHandleStatement.raw) - keyedPrimaryKeyEncodableTableContainer = keyedContainer - container = KeyedEncodingContainer(keyedContainer) - } - if isPrimaryKeyEncoded { - keyedPrimaryKeyEncodableTableContainer?.primaryKeyHash = nil - } else { - keyedPrimaryKeyEncodableTableContainer?.primaryKeyHash = primaryKeyHash - } - return container as! KeyedEncodingContainer - } - - private class KeyedPrimaryKeyEncodableTableContainer { - final var primaryKeyHash: Int? - } - - private final class KeyedEncodingTableContainer - : KeyedPrimaryKeyEncodableTableContainer, KeyedEncodingContainerProtocol { - typealias Key = CodingKeys - - private let handleStatement: HandleStatement - private let hashedKeys: HashedKey - - init(with hashedKeys: HashedKey, - on handleStatement: HandleStatement) { - self.hashedKeys = hashedKeys - self.handleStatement = handleStatement - super.init() - } - - private func bindIndex(by hashValue: Int) -> Int? { - return hashedKeys[hashValue] - } - - func bindPrimaryKeyOrReturnIndex(forKey key: Key) -> Int? { - let hashValue = key.stringValue.hashValue - guard let index = bindIndex(by: hashValue) else { - return nil - } - guard hashValue == primaryKeyHash else { - return index - } - handleStatement.bind(nil, toIndex: index) - return nil - } - - func encodeNil(forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(nil, toIndex: index) - } - - func encode(_ value: Int, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt64(), toIndex: index) - } - - func encode(_ value: Bool, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: Float, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toDouble(), toIndex: index) - } - - func encode(_ value: Double, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value, toIndex: index) - } - - func encode(_ value: String, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value, toIndex: index) - } - - func encode(_ value: Object, forKey key: Key) throws where Object: Encodable { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - //`key` must conform to ColumnEncodable protocol. - let encodableColumnValue = value as! ColumnEncodable - handleStatement.bind(encodableColumnValue.archivedValue(), toIndex: index) - } - - func encode(_ value: Int8, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: Int16, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: Int32, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value, toIndex: index) - } - - func encode(_ value: Int64, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value, toIndex: index) - } - - func encode(_ value: UInt, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt64(), toIndex: index) - } - - func encode(_ value: UInt8, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: UInt16, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: UInt32, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt32(), toIndex: index) - } - - func encode(_ value: UInt64, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - handleStatement.bind(value.toInt64(), toIndex: index) - } - - func encodeIfPresent(_ value: Bool?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Int?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt64(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Int8?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Int16?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Int32?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue, toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Int64?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue, toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: UInt?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt64(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt32(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toInt64(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Float?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue.toDouble(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Double?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue, toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: String?, forKey key: Key) throws { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if let wrappedValue = value { - handleStatement.bind(wrappedValue, toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - func encodeIfPresent(_ value: Object?, - forKey key: Key) throws - where Object: Encodable { - guard let index = bindPrimaryKeyOrReturnIndex(forKey: key) else { - return - } - if value != nil { - //`key` must conform to ColumnEncodable protocol. - let encodableColumnValue = value! as! ColumnEncodable - handleStatement.bind(encodableColumnValue.archivedValue(), toIndex: index) - } else { - handleStatement.bind(nil, toIndex: index) - } - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superEncoder() -> Swift.Encoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func superEncoder(forKey key: Key) -> Swift.Encoder { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedContainer(keyedBy keyType: NestedKey.Type, - forKey key: Key) -> KeyedEncodingContainer - where NestedKey: CodingKey { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - } - - var codingPath: [CodingKey] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - var userInfo: [CodingUserInfoKey: Any] { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func singleValueContainer() -> SingleValueEncodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } - - func unkeyedContainer() -> UnkeyedEncodingContainer { - fatalError("It should not be called. If you think it's a bug, please report an issue to us.") - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/fts/WCDBTokenize.swift b/Example/Pods/WCDB.swift/swift/source/core/fts/WCDBTokenize.swift deleted file mode 100644 index a740d5b2..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/fts/WCDBTokenize.swift +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class WCDBTokenizerInfo: TokenizerInfoBase { - public required init(withArgc argc: Int32, andArgv argv: UnsafePointer?>?) {} -} - -public final class WCDBCursorInfo: CursorInfoBase { - private enum TokenType: UInt { - case basicMultilingualPlaneLetter = 0x00000001 - case basicMultilingualPlaneDigit = 0x00000002 - case basicMultilingualPlaneSymbol = 0x00000003 - case basicMultilingualPlaneOther = 0x0000FFFF - case auxiliaryPlaneOther = 0xFFFFFFFF - } - - private let input: UnsafePointer! - private let inputLength: Int32 - - private var position: Int32 = 0 - private var startOffset: Int32 = 0 - private var endOffset: Int32 = 0 - - private var cursor: Int32 = 0 - private var cursorTokenType: TokenType? - private var cursorTokenLength: Int32 = 0 - private lazy var symbolCharacterSet: CFCharacterSet? = { - var characterSet = CFCharacterSetCreateMutable(kCFAllocatorDefault) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.control)) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.whitespaceAndNewline)) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.nonBase)) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.punctuation)) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.symbol)) - CFCharacterSetUnion(characterSet, CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet.illegal)) - return characterSet - }() - - private var lemmaBuffer: [UInt8] = [] - private var lemmaBufferLength: Int32 = 0 //>0 lemma is not empty - - private var subTokensLengthArray: [UInt8] = [] - private var subTokensCursor: Int32 = 0 - private var subTokensDoubleChar: Bool = false - - private var buffer: [UInt8] = [] - private var bufferLength: Int32 = 0 - - public required init(withInput pInput: UnsafePointer?, count: Int32, tokenizerInfo: TokenizerInfoBase) { - input = pInput - inputLength = count - } - - func cursorStep() -> Int32 { - guard cursor + cursorTokenLength < inputLength else { - cursor = inputLength - cursorTokenType = nil - cursorTokenLength = 0 - return SQLITE_OK - } - cursor += cursorTokenLength - return cursorSetup() - } - - func cursorSetup() -> Int32 { - var rc = SQLITE_OK - let first = UInt8(bitPattern: input.advanced(by: Int(cursor)).pointee) - switch first { - case ..<0xC0: - cursorTokenLength = 1 - switch first { - case 0x30...0x39: - cursorTokenType = .basicMultilingualPlaneDigit - case 0x41...0x5a, 0x61...0x7a: - cursorTokenType = .basicMultilingualPlaneLetter - default: - var result = false - rc = isSymbol(unicodeChar: UInt16(first), result: &result) - guard rc == SQLITE_OK else { - return rc - } - cursorTokenType = result ? .basicMultilingualPlaneSymbol : .basicMultilingualPlaneOther - } - case ..<0xF0: - var unicode: UInt16 = 0 - switch first { - case ..<0xE0: - cursorTokenLength = 2 - unicode = UInt16(first & 0x1F) - default: - cursorTokenLength = 3 - unicode = UInt16(first & 0x0F) - } - for i in cursor+1.. Int32 { - guard let symbolCharacterSet = self.symbolCharacterSet else { - return SQLITE_NOMEM - } - result = CFCharacterSetIsCharacterMember(symbolCharacterSet, unicodeChar) - return SQLITE_OK - } - - static let orthography = NSOrthography(dominantScript: "Latin", languageMap: [ "Latn": ["en"]]) - func lemmatization(input: UnsafePointer, inputLength: Int32) -> Int32 { - if inputLength > buffer.count { - buffer.expand(toNewSize: Int(inputLength)) - } - for i in 0.. String? in - return String(bytes: bytes.baseAddress!.assumingMemoryBound(to: Int8.self), - count: Int(inputLength), - encoding: .ascii) - } - guard let string = optionalString else { - return SQLITE_OK - } - var optionalLemma: String? = nil - string.enumerateLinguisticTags(in: string.startIndex.. 0, - lemma.caseInsensitiveCompare(string) != ComparisonResult.orderedSame else { - return SQLITE_OK - } - lemmaBufferLength = Int32(lemma.count) - if lemmaBufferLength > lemmaBuffer.capacity { - lemmaBuffer.expand(toNewSize: Int(lemmaBufferLength)) - } - memcpy(&lemmaBuffer, lemma.cString, Int(lemmaBufferLength)) - return SQLITE_OK - } - - func subTokensStep() { - self.startOffset = self.subTokensCursor - self.bufferLength = Int32(self.subTokensLengthArray[0]) - if self.subTokensDoubleChar { - if self.subTokensLengthArray.count > 1 { - self.bufferLength += Int32(self.subTokensLengthArray[1]) - self.subTokensDoubleChar = false - } else { - self.subTokensLengthArray.removeAll() - } - } else { - self.subTokensCursor += Int32(subTokensLengthArray[0]) - self.subTokensLengthArray.removeFirst() - self.subTokensDoubleChar = true - } - self.endOffset = self.startOffset + self.bufferLength - } - - public func step(pToken: inout UnsafePointer?, - count: inout Int32, - startOffset: inout Int32, - endOffset: inout Int32, - position: inout Int32) -> Int32 { - var rc = SQLITE_OK - if self.position == 0 { - rc = cursorSetup() - guard rc == SQLITE_OK else { - return rc - } - } - - if self.lemmaBufferLength == 0 { - if self.subTokensLengthArray.isEmpty { - guard self.cursorTokenType != nil else { - return SQLITE_DONE - } - - //Skip symbol - while self.cursorTokenType == .basicMultilingualPlaneSymbol { - rc = cursorStep() - guard rc == SQLITE_OK else { - return rc - } - } - - guard let tokenType = self.cursorTokenType else { - return SQLITE_DONE - } - - switch tokenType { - case .basicMultilingualPlaneLetter: - fallthrough - case .basicMultilingualPlaneDigit: - self.startOffset = self.cursor - repeat { - rc = cursorStep() - }while(rc == SQLITE_OK && self.cursorTokenType == tokenType) - guard rc == SQLITE_OK else { - return rc - } - self.endOffset = self.cursor - self.bufferLength = self.endOffset - self.startOffset - case .basicMultilingualPlaneOther: - fallthrough - case .auxiliaryPlaneOther: - self.subTokensLengthArray.append(UInt8(self.cursorTokenLength)) - self.subTokensCursor = self.cursor - self.subTokensDoubleChar = true - rc = cursorStep() - while rc == SQLITE_OK && self.cursorTokenType == tokenType { - self.subTokensLengthArray.append(UInt8(cursorTokenLength)) - rc = cursorStep() - } - guard rc == SQLITE_OK else { - return rc - } - subTokensStep() - default: break - } - if tokenType == .basicMultilingualPlaneLetter { - rc = lemmatization(input: self.input.advanced(by: Int(self.startOffset)), - inputLength: self.bufferLength) - guard rc == SQLITE_OK else { - return rc - } - } else { - if self.bufferLength > self.buffer.count { - self.buffer.expand(toNewSize: Int(self.bufferLength)) - } - memcpy(&self.buffer, input.advanced(by: Int(self.startOffset)), Int(self.bufferLength)) - } - } else { - subTokensStep() - if self.bufferLength > self.buffer.capacity { - self.buffer.expand(toNewSize: Int(self.bufferLength)) - } - memcpy(&self.buffer, input.advanced(by: Int(self.startOffset)), Int(self.bufferLength)) - } - - pToken = self.buffer.withUnsafeBytes { (bytes) -> UnsafePointer in - return bytes.baseAddress!.assumingMemoryBound(to: Int8.self) - } - count = self.bufferLength - } else { - pToken = self.lemmaBuffer.withUnsafeBytes { (bytes) -> UnsafePointer in - return bytes.baseAddress!.assumingMemoryBound(to: Int8.self) - } - count = self.lemmaBufferLength - self.lemmaBufferLength = 0 - } - - startOffset = self.startOffset - endOffset = self.endOffset - self.position += 1 - position = self.position - - return SQLITE_OK - } -} - -public final class WCDBModule: Module { - public typealias TokenizerInfo = WCDBTokenizerInfo - public typealias CursorInfo = WCDBCursorInfo - - public static let name = "WCDB" - - public private(set) static var module = sqlite3_tokenizer_module( - iVersion: 0, - xCreate: { (argc, argv, ppTokenizer) -> Int32 in - return WCDBModule.create(argc: argc, argv: argv, ppTokenizer: ppTokenizer) - }, - xDestroy: { (pTokenizer) -> Int32 in - return WCDBModule.destroy(pTokenizer: pTokenizer) - }, - xOpen: { (pTokenizer, pInput, nBytes, ppCursor) -> Int32 in - return WCDBModule.open(pTokenizer: pTokenizer, pInput: pInput, nBytes: nBytes, ppCursor: ppCursor) - }, - xClose: { (pCursor) -> Int32 in - return WCDBModule.close(pCursor: pCursor) - }, - xNext: { (pCursor, ppToken, pnBytes, piStartOffset, piEndOffset, piPosition) -> Int32 in - return WCDBModule.next(pCursor: pCursor, - ppToken: ppToken, - pnBytes: pnBytes, - piStartOffset: piStartOffset, - piEndOffset: piEndOffset, - piPosition: piPosition) - }, - xLanguageid: nil) - - public static let address = { () -> Data in - var pointer = UnsafeMutableRawPointer(&module) - return Data(bytes: &pointer, count: MemoryLayout.size(ofValue: pointer)) - }() -} - -extension Tokenize { - public static let WCDB = Tokenize(module: WCDBModule.self) -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/ChainCall.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/ChainCall.swift deleted file mode 100644 index 8a54edd0..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/ChainCall.swift +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// ChainCall interface for inserting -public protocol InsertChainCallInterface: AnyObject { - - /// Prepare chain call for inserting of `TableEncodable` object - /// - /// - Parameters: - /// - cls: Type of table codable object - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsert(of cls: Root.Type, intoTable table: String) throws -> Insert - - /// Prepare chain call for inserting or replacing of `TableEncodable` object - /// - /// - Parameters: - /// - cls: Type of table codable object - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsertOrReplace(of cls: Root.Type, intoTable table: String) throws -> Insert - - /// Prepare chain call for inserting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsert(on propertyConvertibleList: PropertyConvertible..., intoTable table: String) throws -> Insert - - /// Prepare chain call for inserting or replacing on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsertOrReplace(on propertyConvertibleList: PropertyConvertible..., - intoTable table: String) throws -> Insert - - /// Prepare chain call for inserting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsert(on propertyConvertibleList: [PropertyConvertible], - intoTable table: String) throws -> Insert - - /// Prepare chain call for inserting or replacing on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Returns: `Insert` - /// - Throws: `Error` - func prepareInsertOrReplace(on propertyConvertibleList: [PropertyConvertible], - intoTable table: String) throws -> Insert -} - -extension InsertChainCallInterface where Self: Core { - public func prepareInsert(of cls: Root.Type, intoTable table: String) throws -> Insert { - return try Insert(with: self, named: table, on: cls.Properties.all, isReplace: false) - } - - public func prepareInsertOrReplace( - of cls: Root.Type, - intoTable table: String) throws -> Insert { - return try Insert(with: self, named: table, on: cls.Properties.all, isReplace: true) - } - - public func prepareInsert(on propertyConvertibleList: PropertyConvertible..., - intoTable table: String) throws -> Insert { - return try prepareInsert(on: propertyConvertibleList, intoTable: table) - } - - public func prepareInsertOrReplace(on propertyConvertibleList: PropertyConvertible..., - intoTable table: String) throws -> Insert { - return try prepareInsertOrReplace(on: propertyConvertibleList, intoTable: table) - } - - public func prepareInsert(on propertyConvertibleList: [PropertyConvertible], - intoTable table: String) throws -> Insert { - return try Insert(with: self, named: table, on: propertyConvertibleList, isReplace: false) - } - - public func prepareInsertOrReplace(on propertyConvertibleList: [PropertyConvertible], - intoTable table: String) throws -> Insert { - return try Insert(with: self, named: table, on: propertyConvertibleList, isReplace: true) - } -} - -/// ChainCall interface for deleting -public protocol DeleteChainCallInterface: AnyObject { - - /// Prepare chain call for deleting on specific properties - /// - /// - Parameter table: Table name - /// - Returns: `Delete` - /// - Throws: `Error` - func prepareDelete(fromTable table: String) throws -> Delete -} - -extension DeleteChainCallInterface where Self: Core { - public func prepareDelete(fromTable table: String) throws -> Delete { - return try Delete(with: self, andTableName: table) - } -} - -/// ChainCall interface for updating -public protocol UpdateChainCallInterface: AnyObject { - - /// Prepare chain call for updating on specific properties - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Returns: `Update` - /// - Throws: `Error` - func prepareUpdate(table: String, on propertyConvertibleList: PropertyConvertible...) throws -> Update - - /// Prepare chain call for updating on specific properties - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Returns: `Update` - /// - Throws: `Error` - func prepareUpdate(table: String, on propertyConvertibleList: [PropertyConvertible]) throws -> Update -} - -extension UpdateChainCallInterface where Self: Core { - public func prepareUpdate(table: String, on propertyConvertibleList: PropertyConvertible...) throws -> Update { - return try prepareUpdate(table: table, on: propertyConvertibleList) - } - - public func prepareUpdate(table: String, on propertyConvertibleList: [PropertyConvertible]) throws -> Update { - return try Update(with: self, on: propertyConvertibleList, andTable: table) - } -} - -/// ChainCall interface for row-selecting -public protocol RowSelectChainCallInterface: AnyObject { - - /// Prepare chain call for row-selecting on specific column results - /// - /// - Parameters: - /// - columnResultConvertibleList: `ColumnResult` list - /// - tables: Table name list - /// - isDistinct: Is distinct or not - /// - Returns: `RowSelect` - /// - Throws: `Error` - func prepareRowSelect(on columnResultConvertibleList: ColumnResultConvertible..., - fromTables tables: [String], - isDistinct: Bool) throws -> RowSelect - - /// Prepare chain call for row-selecting on specific column results - /// - /// - Parameters: - /// - columnResultConvertibleList: `ColumnResult` list - /// - tables: Table name list - /// - isDistinct: Is distinct or not - /// - Returns: `RowSelect` - /// - Throws: `Error` - func prepareRowSelect(on columnResultConvertibleList: [ColumnResultConvertible], - fromTables tables: [String], - isDistinct: Bool) throws -> RowSelect - - /// Prepare chain call for row-selecting on specific column results - /// - /// - Parameters: - /// - columnResultConvertibleList: `ColumnResult` list - /// - tables: Table name - /// - isDistinct: Is distinct or not - /// - Returns: `RowSelect` - /// - Throws: `Error` - func prepareRowSelect(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - isDistinct: Bool) throws -> RowSelect - - /// Prepare chain call for row-selecting on specific column results - /// - /// - Parameters: - /// - columnResultConvertibleList: `ColumnResult` list - /// - tables: Table name - /// - isDistinct: Is distinct or not - /// - Returns: `RowSelect` - /// - Throws: `Error` - func prepareRowSelect(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - isDistinct: Bool) throws -> RowSelect -} - -extension RowSelectChainCallInterface where Self: Core { - public func prepareRowSelect(on columnResultConvertibleList: ColumnResultConvertible..., - fromTables tables: [String], - isDistinct: Bool = false) throws -> RowSelect { - return try prepareRowSelect(on: columnResultConvertibleList.isEmpty ? - [Column.all] : columnResultConvertibleList, - fromTables: tables, - isDistinct: isDistinct) - } - - public func prepareRowSelect(on columnResultConvertibleList: [ColumnResultConvertible], - fromTables tables: [String], - isDistinct: Bool = false) throws -> RowSelect { - return try RowSelect(with: self, results: columnResultConvertibleList, tables: tables, isDistinct: isDistinct) - } - - public func prepareRowSelect(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - isDistinct: Bool = false) throws -> RowSelect { - return try prepareRowSelect(on: columnResultConvertibleList.isEmpty ? - [Column.all] : columnResultConvertibleList, - fromTable: table, - isDistinct: isDistinct) - } - - public func prepareRowSelect(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - isDistinct: Bool = false) throws -> RowSelect { - return try RowSelect(with: self, - results: columnResultConvertibleList, - tables: [table], - isDistinct: isDistinct) - } -} - -/// ChainCall interface for selecting -public protocol SelectChainCallInterface: AnyObject { - - /// Prepare chain call for selecting of `TableDecodable` object - /// - /// - Parameters: - /// - cls: Type of table decodable object - /// - table: Table name - /// - isDistinct: Is distinct or not - /// - Returns: `Select` - /// - Throws: `Error` - func prepareSelect(of cls: Root.Type, - fromTable table: String, - isDistinct: Bool) throws -> Select - - /// Prepare chain call for selecting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - isDistinct: Is distinct or not - /// - Returns: `Select` - /// - Throws: `Error` - func prepareSelect(on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - isDistinct: Bool) throws -> Select - - /// Prepare chain call for selecting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - isDistinct: Is distinct or not - /// - Returns: `Select` - /// - Throws: `Error` - func prepareSelect(on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - isDistinct: Bool) throws -> Select -} - -extension SelectChainCallInterface where Self: Core { - public func prepareSelect(of cls: Root.Type, - fromTable table: String, - isDistinct: Bool = false) throws -> Select { - return try Select(with: self, on: cls.Properties.all, table: table, isDistinct: isDistinct) - } - - public func prepareSelect(on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - isDistinct: Bool = false) throws -> Select { - return try prepareSelect(on: propertyConvertibleList, - fromTable: table, - isDistinct: isDistinct) - } - - public func prepareSelect(on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - isDistinct: Bool = false) throws -> Select { - return try Select(with: self, on: propertyConvertibleList, table: table, isDistinct: isDistinct) - } -} - -/// ChainCall interface for multi-selecting -public protocol MultiSelectChainCallInterface: AnyObject { - - /// Prepare chain call for multi-selecting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - tables: Table name list - /// - Returns: `MultiSelect` - /// - Throws: `Error` - func prepareMultiSelect(on propertyConvertibleList: PropertyConvertible..., - fromTables tables: [String]) throws -> MultiSelect - - /// Prepare chain call for multi-selecting on specific properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - tables: Table name list - /// - Returns: `MultiSelect` - /// - Throws: `Error` - func prepareMultiSelect(on propertyConvertibleList: [PropertyConvertible], - fromTables tables: [String]) throws -> MultiSelect -} - -extension MultiSelectChainCallInterface where Self: Core { - public func prepareMultiSelect(on propertyConvertibleList: PropertyConvertible..., - fromTables tables: [String]) throws -> MultiSelect { - return try prepareMultiSelect(on: propertyConvertibleList, fromTables: tables) - } - - public func prepareMultiSelect(on propertyConvertibleList: [PropertyConvertible], - fromTables tables: [String]) throws -> MultiSelect { - return try MultiSelect(with: self, on: propertyConvertibleList, tables: tables) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Declare.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Declare.swift deleted file mode 100644 index 607b713e..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Declare.swift +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public typealias Condition = ExpressionConvertible -public typealias Limit = ExpressionConvertible -public typealias Offset = ExpressionConvertible -public typealias GroupBy = ExpressionConvertible -public typealias Having = ExpressionConvertible -public typealias OrderBy = OrderConvertible diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Delete.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Delete.swift deleted file mode 100644 index 97e0db98..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Delete.swift +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Chain call for deleting -public final class Delete { - private var core: Core - private let statement = StatementDelete() - - /// The number of changed rows in the most recent call. - /// It should be called after executing successfully - public var changes: Int? - - init(with core: Core, andTableName tableName: String) throws { - guard tableName.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .delete, - code: .misuse, - message: "Nil table name") - } - statement.delete(fromTable: tableName) - self.core = core - } - - /// WINQ interface for SQL - /// - /// - Parameter condition: Expression convertible - /// - Returns: `self` - @discardableResult - public func `where`(_ condition: Condition) -> Delete { - statement.where(condition) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public func order(by orderList: OrderBy...) -> Delete { - return order(by: orderList) - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public func order(by orderList: [OrderBy]) -> Delete { - statement.order(by: orderList) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameters: - /// - begin: Expression convertible - /// - end: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(from begin: Limit, to end: Limit) -> Delete { - statement.limit(from: begin, to: end) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter limit: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(_ limit: Limit) -> Delete { - statement.limit(limit) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameters: - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(_ limit: Limit, offset: Offset) -> Delete { - statement.limit(limit, offset: offset) - return self - } - - /// Execute the delete chain call. - /// - /// - Throws: Error - public func execute() throws { - let recyclableHandleStatement: RecyclableHandleStatement = try core.prepare(statement) - let handleStatement = recyclableHandleStatement.raw - try handleStatement.step() - changes = handleStatement.changes - } -} - -extension Delete: CoreRepresentable { - - /// The tag of the related database. - public var tag: Tag? { - return core.tag - } - - /// The path of the related database. - public var path: String { - return core.path - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Insert.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Insert.swift deleted file mode 100644 index 80e1104f..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Insert.swift +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Chain call for inserting -public final class Insert { - private let core: Core - private var properties: [PropertyConvertible]? - private let name: String - private let isReplace: Bool - - init(with core: Core, - named name: String, - on propertyConvertibleList: [PropertyConvertible]?, - isReplace: Bool = false) throws { - guard name.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .insert, - code: .misuse, - message: "Empty table name") - } - self.name = name - self.properties = propertyConvertibleList - self.isReplace = isReplace - self.core = core - } - - private var conflict: Conflict? { - return isReplace ? Conflict.replace : nil - } - - private lazy var statement: StatementInsert = StatementInsert() - .insert(intoTable: name, - with: properties!, - onConflict: self.conflict) - .values(Array(repeating: Expression.bindParameter, count: properties!.count)) - - /// Execute the insert chain call with objects. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameter objects: Object to be inserted - /// - Throws: Error - public func execute(with objects: Object...) throws { - try execute(with: objects) - } - - /// Execute the insert chain call with objects. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameter objects: Object to be inserted - /// - Throws: Error - public func execute(with objects: [Object]) throws { - guard objects.count > 0 else { - Error.warning("Inserting with an empty/nil object") - return - } - let orm = Object.CodingKeys.objectRelationalMapping - func doInsertObject() throws { - properties = properties ?? Object.Properties.all - let recyclableHandleStatement: RecyclableHandleStatement = try core.prepare(statement) - let handleStatement = recyclableHandleStatement.raw - let encoder = TableEncoder(properties!.asCodingTableKeys(), on: recyclableHandleStatement) - if !isReplace { - encoder.primaryKeyHash = orm.getPrimaryKey()?.stringValue.hashValue - } - - for var object in objects { - let isAutoIncrement = object.isAutoIncrement - encoder.isPrimaryKeyEncoded = !isAutoIncrement - try object.encode(to: encoder) - try handleStatement.step() - if !isReplace && isAutoIncrement { - object.lastInsertedRowID = handleStatement.lastInsertedRowID - } - try handleStatement.reset() - } - } - return objects.count == 1 ? try doInsertObject() : try core.run(embeddedTransaction: doInsertObject ) - } -} - -extension Insert: CoreRepresentable { - /// The tag of the related database. - public var tag: Tag? { - return core.tag - } - - /// The path of the related database. - public var path: String { - return core.path - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Interface.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Interface.swift deleted file mode 100644 index 203a2520..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Interface.swift +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Convenient interface for inserting -public protocol InsertInterface: AnyObject { - - /// Execute inserting with `TableEncodable` object on specific(or all) properties - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Throws: `Error` - func insert( - objects: Object..., - on propertyConvertibleList: [PropertyConvertible]?, - intoTable table: String) throws - - /// Execute inserting with `TableEncodable` object on specific(or all) properties - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Throws: `Error` - func insert( - objects: [Object], - on propertyConvertibleList: [PropertyConvertible]?, - intoTable table: String) throws - - /// Execute inserting or replacing with `TableEncodable` object on specific(or all) properties. - /// It will replace the original row while they have same primary key or row id. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Throws: `Error` - func insertOrReplace( - objects: Object..., - on propertyConvertibleList: [PropertyConvertible]?, - intoTable table: String) throws - - /// Execute inserting or replacing with `TableEncodable` object on specific(or all) properties. - /// It will replace the original row while they have same primary key or row id. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - Throws: `Error` - func insertOrReplace( - objects: [Object], - on propertyConvertibleList: [PropertyConvertible]?, - intoTable table: String) throws -} - -extension InsertInterface where Self: Core { - public func insert( - objects: [Object], - on propertyConvertibleList: [PropertyConvertible]? = nil, - intoTable table: String) throws { - let insert = try Insert(with: self, named: table, on: propertyConvertibleList, isReplace: false) - return try insert.execute(with: objects) - } - - public func insertOrReplace( - objects: [Object], - on propertyConvertibleList: [PropertyConvertible]? = nil, - intoTable table: String) throws { - let insert = try Insert(with: self, named: table, on: propertyConvertibleList, isReplace: true) - return try insert.execute(with: objects) - } - - public func insert( - objects: Object..., - on propertyConvertibleList: [PropertyConvertible]? = nil, - intoTable table: String) throws { - return try insert(objects: objects, on: propertyConvertibleList, intoTable: table) - } - - public func insertOrReplace( - objects: Object..., - on propertyConvertibleList: [PropertyConvertible]? = nil, - intoTable table: String) throws { - return try insertOrReplace(objects: objects, on: propertyConvertibleList, intoTable: table) - } -} - -/// Convenient interface for updating -public protocol UpdateInterface: AnyObject { - - /// Execute updating with `TableEncodable` object on specific(or all) properties. - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - func update( - table: String, - on propertyConvertibleList: PropertyConvertible..., - with object: Object, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - - /// Execute updating with `TableEncodable` object on specific(or all) properties. - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - func update( - table: String, - on propertyConvertibleList: [PropertyConvertible], - with object: Object, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - - /// Execute updating with row on specific(or all) properties. - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - func update(table: String, - on propertyConvertibleList: PropertyConvertible..., - with row: [ColumnEncodable], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - - /// Execute updating with row on specific(or all) properties. - /// - /// - Parameters: - /// - table: Table name - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - func update(table: String, - on propertyConvertibleList: [PropertyConvertible], - with row: [ColumnEncodable], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -} - -extension UpdateInterface where Self: Core { - public func update( - table: String, - on propertyConvertibleList: [PropertyConvertible], - with object: Object, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let update = try Update(with: self, on: propertyConvertibleList, andTable: table) - if condition != nil { - update.where(condition!) - } - if orderList != nil { - update.order(by: orderList!) - } - if limit != nil { - if offset != nil { - update.limit(limit!, offset: offset!) - } else { - update.limit(limit!) - } - } - return try update.execute(with: object) - } - - public func update( - table: String, - on propertyConvertibleList: PropertyConvertible..., - with object: Object, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - return try update(table: table, - on: propertyConvertibleList, - with: object, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - public func update(table: String, - on propertyConvertibleList: PropertyConvertible..., - with row: [ColumnEncodable], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - return try update(table: table, - on: propertyConvertibleList, - with: row, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - public func update(table: String, - on propertyConvertibleList: [PropertyConvertible], - with row: [ColumnEncodable], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let update = try Update(with: self, on: propertyConvertibleList, andTable: table) - if condition != nil { - update.where(condition!) - } - if orderList != nil { - update.order(by: orderList!) - } - if limit != nil { - if offset != nil { - update.limit(limit!, offset: offset!) - } else { - update.limit(limit!) - } - } - return try update.execute(with: row) - } -} - -/// Convenient interface for deleting -public protocol DeleteInterface: AnyObject { - - /// Execute deleting - /// - /// - Parameters: - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - func delete(fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -} - -extension DeleteInterface where Self: Core { - public func delete(fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let delete = try Delete(with: self, andTableName: table) - if condition != nil { - delete.where(condition!) - } - if orderList != nil { - delete.order(by: orderList!) - } - if limit != nil { - if offset != nil { - delete.limit(limit!, offset: offset!) - } else { - delete.limit(limit!) - } - } - return try delete.execute() - } -} - -/// Convenient interface for row selecting -public protocol RowSelectInterface: AnyObject { - - /// Get rows by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - func getRows(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalRowXColumn - - /// Get rows by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - func getRows(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalRowXColumn - - /// Get row by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalRow` - /// - Throws: `Error` - func getRow(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> FundamentalRow - - /// Get row by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalRow` - /// - Throws: `Error` - func getRow(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> FundamentalRow - - /// Get column by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalColumn` - /// - Throws: `Error` - func getColumn(on columnResultConvertible: ColumnResultConvertible, - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalColumn - - /// Get distinct column by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalColumn` - /// - Throws: `Error` - func getDistinctColumn(on columnResultConvertible: ColumnResultConvertible, - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalColumn - - /// Get value by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalValue` - /// - Throws: `Error` - func getValue(on columnResultConvertible: ColumnResultConvertible, - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalValue - - /// Get distinct value by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalValue` - /// - Throws: `Error` - func getDistinctValue(on result: ColumnResultConvertible, - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalValue -} - -extension RowSelectInterface where Self: Core { - public func getRows(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalRowXColumn { - let rowSelect = try RowSelect(with: self, - results: columnResultConvertibleList, - tables: [table], - isDistinct: false) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allRows() - } - - public func getRows(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalRowXColumn { - return try getRows( - on: columnResultConvertibleList.isEmpty ? [Column.all] : columnResultConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - public func getRow(on columnResultConvertibleList: ColumnResultConvertible..., - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> FundamentalRow { - return try getRow( - on: columnResultConvertibleList.isEmpty ? [Column.all] : columnResultConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - offset: offset) - } - - public func getRow(on columnResultConvertibleList: [ColumnResultConvertible], - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> FundamentalRow { - return try getRows(on: columnResultConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first ?? [] - } - - public func getColumn(on result: ColumnResultConvertible, - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalColumn { - let rowSelect = try RowSelect(with: self, results: [result], tables: [table], isDistinct: false) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allValues() - } - - public func getDistinctColumn(on result: ColumnResultConvertible, - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalColumn { - let rowSelect = try RowSelect(with: self, results: [result], tables: [table], isDistinct: true) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allValues() - } - - public func getValue(on result: ColumnResultConvertible, - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalValue { - return (try getRows(on: result, - fromTable: table, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first?.first) ?? FundamentalValue(nil) - } - - public func getDistinctValue(on result: ColumnResultConvertible, - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalValue { - return (try getDistinctColumn(on: result, fromTable: table).first) ?? FundamentalValue(nil) - } -} - -/// Convenient interface for selecting -public protocol SelectInterface: AnyObject { - //TODO: Add generic property convertible to fit the type - - /// Get objects on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - func getObjects( - on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> [Object] - - /// Get objects on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - func getObjects( - on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> [Object] - - /// Get object on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - func getObject( - on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> Object? - - /// Get object on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - table: Table name - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - condition: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - func getObject( - on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> Object? -} - -extension SelectInterface where Self: Core { - public func getObjects( - on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> [Object] { - let select = try Select(with: self, on: propertyConvertibleList, table: table, isDistinct: false) - if condition != nil { - select.where(condition!) - } - if orderList != nil { - select.order(by: orderList!) - } - if limit != nil { - if offset != nil { - select.limit(limit!, offset: offset!) - } else { - select.limit(limit!) - } - } - return try select.allObjects() - } - - public func getObjects( - on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> [Object] { - return try getObjects(on: propertyConvertibleList.isEmpty ? Object.Properties.all : propertyConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - public func getObject( - on propertyConvertibleList: [PropertyConvertible], - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> Object? { - return try getObjects(on: propertyConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first - } - - public func getObject( - on propertyConvertibleList: PropertyConvertible..., - fromTable table: String, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> Object? { - return try getObject(on: propertyConvertibleList.isEmpty ? Object.Properties.all : propertyConvertibleList, - fromTable: table, - where: condition, - orderBy: orderList, - offset: offset) - } -} - -/// Convenient interface for table related operation -public protocol TableInterface: AnyObject { - /// Create table, related indexes and constraints with specific type - /// - /// Note that it will create defined indexes automatically. - /// The name of index is `"\(tableName)\(indexSubfixName)"` while `indexSubfixName` is defined by `IndexBinding`. - /// BUT, it will not drop the undefined indexes. You should drop it manually. - /// - /// Note that it will add the newly defined column automatically. - /// AND, it will skip the undefined column. It can be very developer-friendly while upgrading your database column. - /// - /// Note that it will run embedded transaction - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - name: Table name. - /// - rootType: Type of table encodable object - /// - Throws: `Error` - func create(table name: String, of rootType: Root.Type) throws - - /// Create virtual table and constraints with specific type - /// - /// Note that it will run embedded transaction - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - name: Table name. - /// - rootType: Type of table encodable object - /// - Throws: `Error` - func create(virtualTable name: String, of rootType: Root.Type) throws - - /// Create table manually - /// - /// - Parameters: - /// - name: Table name - /// - columnDefList: WINQ column definition list - /// - constraintList: WINQ constraint list. - /// - Throws: `Error` - func create(table name: String, with columnDefList: [ColumnDef], and constraintList: [TableConstraint]?) throws - - /// Create table manually - /// - /// - Parameters: - /// - name: Table name - /// - columnDefList: WINQ column definition list - /// - constraintList: WINQ constraint list. - /// - Throws: `Error` - func create(table name: String, with columnDefList: ColumnDef..., and constraintList: [TableConstraint]?) throws - - /// Create new column - /// - /// - Parameters: - /// - columnDef: WINQ column definition - /// - table: Table name - /// - Throws: `Error` - func addColumn(with columnDef: ColumnDef, forTable table: String) throws - - /// Drop table - /// - /// - Parameter name: Table name - /// - Throws: `Erro` - func drop(table name: String) throws - - /// Create index manually - /// - /// - Parameters: - /// - name: Index name - /// - columnIndexConvertibleList: WINQ column index list - /// - table: Table name - /// - Throws: `Error` - func create(index name: String, - with columnIndexConvertibleList: [ColumnIndexConvertible], - forTable table: String) throws - - /// Create index manually - /// - /// - Parameters: - /// - name: Index name - /// - columnIndexConvertibleList: WINQ column index list - /// - table: Table name - /// - Throws: `Error` - func create(index name: String, - with columnIndexConvertibleList: ColumnIndexConvertible..., - forTable table: String) throws - - /// Drop index - /// - /// - Parameter name: Index name - /// - Throws: `Error` - func drop(index name: String) throws -} - -extension TableInterface where Self: Core { - public func create( - table name: String, - of rootType: Root.Type) throws { - try run(embeddedTransaction: { - let orm = Root.CodingKeys.objectRelationalMapping - if try isTableExists(name) { - var columnNames: [String] = [] - do { - let statementPragma = StatementPragma().pragma(.tableInfo, to: name) - let recyclableHandleStatement: RecyclableHandleStatement = try prepare(statementPragma) - let handleStatement = recyclableHandleStatement.raw - while try handleStatement.step() { - let columnName: String = handleStatement.columnValue(atIndex: 1) - columnNames.append(columnName) - } - } - var keys = orm.allKeys - for columnName in columnNames { - if let index = keys.firstIndex(where: { (key) -> Bool in - return key.stringValue.caseInsensitiveCompare(columnName) == ComparisonResult.orderedSame - }) { - keys.remove(at: index) - } else { - Error.warning("Skip column named [\(columnName)] for table [\(name)]") - } - } - try keys.forEach { - try exec(StatementAlterTable().alter(table: name).addColumn(with: orm.generateColumnDef(with: $0))) - } - } else { - try exec(orm.generateCreateTableStatement(named: name)) - } - try orm.generateCreateIndexStatements(onTable: name)?.forEach { try exec($0) } - }) - } - - public func create(virtualTable name: String, of rootType: Root.Type) throws { - try run(transaction: { - try exec(rootType.CodingKeys.objectRelationalMapping.generateCreateVirtualTableStatement(named: name)) - }) - } - - public func create(table name: String, - with columnDefList: ColumnDef..., - and constraintList: [TableConstraint]? = nil) throws { - try create(table: name, with: columnDefList, and: constraintList) - } - - public func create(table name: String, - with columnDefList: [ColumnDef], - and constraintList: [TableConstraint]? = nil) throws { - try exec(StatementCreateTable().create(table: name, with: columnDefList, and: constraintList)) - } - - public func addColumn(with columnDef: ColumnDef, forTable table: String) throws { - try exec(StatementAlterTable().alter(table: table).addColumn(with: columnDef)) - } - - public func drop(table name: String) throws { - try exec(StatementDropTable().drop(table: name)) - } - - public func create(index name: String, - with columnIndexConvertibleList: ColumnIndexConvertible..., - forTable table: String) throws { - try create(index: name, with: columnIndexConvertibleList, forTable: table) - } - - public func create(index name: String, - with columnIndexConvertibleList: [ColumnIndexConvertible], - forTable table: String) throws { - try exec(StatementCreateIndex().create(index: name).on(table: table, indexesBy: columnIndexConvertibleList)) - } - - public func drop(index name: String) throws { - try exec(StatementDropIndex().drop(index: name)) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/MultiSelect.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/MultiSelect.swift deleted file mode 100644 index d3f7f0f2..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/MultiSelect.swift +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Chain call for multi-selecting -public final class MultiSelect: Selectable { - private let keys: [CodingTableKeyBase] - - init(with core: Core, - on propertyConvertibleList: [PropertyConvertible], - tables: [String], - isDistinct: Bool = false) throws { - guard propertyConvertibleList.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .select, - code: .misuse, - message: "Selecting nothing from \(tables) is invalid") - } - guard tables.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .select, - code: .misuse, - message: "Empty table") - } - self.keys = propertyConvertibleList.map({ (propertyConvertible) -> CodingTableKeyBase in - let codingTableKey = propertyConvertible.codingTableKey - assert(codingTableKey.rootType is TableDecodableBase.Type, - "\(codingTableKey.rootType) must conform to TableDecodable protocol.") - return codingTableKey - }) - - let statement = StatementSelect().select(distinct: isDistinct, propertyConvertibleList).from(tables) - super.init(with: core, statement: statement) - } - - private typealias Generator = () throws -> TableDecodableBase - - struct TypedIndexedKeys { - let type: TableDecodableBase.Type - var indexedKeys: TableDecoder.HashedKey - init(_ type: TableDecodableBase.Type, key: String, index: Int) { - self.type = type - self.indexedKeys = [key.hashValue: index] - } - } - private lazy var generators: [String: Generator] = { - var mappedKeys: [String: TypedIndexedKeys] = [:] - let handleStatement = try? lazyHandleStatement() - assert(handleStatement != nil, - "It should not be failed. If you think it's a bug, please report an issue to us.") - for (index, key) in keys.enumerated() { - let tableName = handleStatement!.columnTableName(atIndex: index) - var typedIndexedKeys: TypedIndexedKeys! = mappedKeys[tableName] - if typedIndexedKeys == nil { - let tableDecodableType = key.rootType as? TableDecodableBase.Type - assert(tableDecodableType != nil, - "\(key.rootType) must conform to TableDecodable protocol.") - typedIndexedKeys = TypedIndexedKeys(tableDecodableType!, key: key.stringValue, index: index) - } else { - typedIndexedKeys.indexedKeys[key.stringValue.hashValue] = index - } - mappedKeys[tableName] = typedIndexedKeys - } - var generators: [String: Generator] = [:] - for (tableName, typedIndexedKey) in mappedKeys { - let decoder = TableDecoder(typedIndexedKey.indexedKeys, on: optionalRecyclableHandleStatement!) - let type = typedIndexedKey.type - let generator = { () throws -> TableDecodableBase in - return try type.init(from: decoder) - } - generators[tableName] = generator - } - return generators - }() - - private func extractMultiObject() throws -> [String: TableDecodableBase] { - var multiObject: [String: TableDecodableBase] = [:] - for (tableName, generator) in generators { - multiObject[tableName] = try generator() - } - return multiObject - } - - /// Get next selected object. You can do an iteration using it. - /// - /// while let multiObject = try self.nextMultiObject() { - /// let object1 = multiObject[tableName1] - /// let object2 = multiObject[tableName2] - /// //... - /// } - /// - /// - Returns: Mapping from table name to object. Nil means the end of iteration. - /// - Throws: `Error` - public func nextMultiObject() throws -> [String: TableDecodableBase]? { - guard try next() else { - return nil - } - return try extractMultiObject() - } - - /// Get all selected objects. - /// - /// - Returns: Array contained mapping from table name to object. - /// - Throws: `Error` - public func allMultiObjects() throws -> [[String: TableDecodableBase]] { - var multiObjects: [[String: TableDecodableBase]] = [] - while try next() { - multiObjects.append(try extractMultiObject()) - } - return multiObjects - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/RowSelect.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/RowSelect.swift deleted file mode 100644 index b32ad90c..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/RowSelect.swift +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Chain call for row-selecting -public final class RowSelect: Selectable { - init(with core: Core, - results columnResultConvertibleList: [ColumnResultConvertible], - tables: [String], - isDistinct: Bool) throws { - guard tables.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .select, - code: .misuse, - message: "Empty table") - } - let statement = StatementSelect().select(distinct: isDistinct, columnResultConvertibleList).from(tables) - super.init(with: core, statement: statement) - } - - private func extract(atIndex index: Int) throws -> FundamentalValue { - let handleStatement = try self.lazyHandleStatement() - switch handleStatement.columnType(atIndex: index) { - case .integer32: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Int32.self)) - case .integer64: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Int64.self)) - case .float: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Double.self)) - case .text: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: String.self)) - case .BLOB: - return FundamentalValue(handleStatement.columnValue(atIndex: index, of: Data.self)) - case .null: - return FundamentalValue(nil) - } - } - - private func extract() throws -> FundamentalRow { - var row: FundamentalRow = [] - let handleStatement = try self.lazyHandleStatement() - for index in 0.. FundamentalRow? { - guard try next() else { - return nil - } - return try extract() - } - - /// Get all selected row. - /// - /// - Returns: Array with `Array` - /// - Throws: `Error` - public func allRows() throws -> FundamentalRowXColumn { - var rows: [[FundamentalValue]] = [] - while try next() { - rows.append(try extract()) - } - return rows - } - - /// Get next selected value. You can do an iteration using it. - /// - /// while let value = try nextValue() { - /// print(value.int32Value) - /// } - /// - /// - Returns: `FundamentalValue`. Nil means the end of iteration. - /// - Throws: `Error` - public func nextValue() throws -> FundamentalValue? { - guard try next() else { - return nil - } - return try extract(atIndex: 0) - } - - /// Get all selected values. - /// - /// - Returns: Array with `FundamentalValue`. - /// - Throws: `Error` - public func allValues() throws -> FundamentalColumn { - var values: [FundamentalValue] = [] - while try next() { - values.append(try extract(atIndex: 0)) - } - return values - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Select.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Select.swift deleted file mode 100644 index dbe14c21..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Select.swift +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public final class Select: Selectable { - private let keys: [CodingTableKeyBase] - - private lazy var decoder = TableDecoder(keys, on: optionalRecyclableHandleStatement!) - - init(with core: Core, on propertyConvertibleList: [PropertyConvertible], table: String, isDistinct: Bool) throws { - //TODO: Use generic to check all coding table keys conform to same root type - keys = propertyConvertibleList.asCodingTableKeys() - let statement = StatementSelect().select(distinct: isDistinct, propertyConvertibleList).from(table) - super.init(with: core, statement: statement) - } - - /// Get next selected object according to the `CodingTableKey`. You can do an iteration using it. - /// - /// - Returns: Table decodable object according to the `CodingTableKey`. Nil means the end of iteration. - /// - Throws: `Error` - public func nextObject() throws -> Any? { - let rootType = keys[0].rootType as? TableDecodableBase.Type - assert(rootType != nil, "\(keys[0].rootType) must conform to TableDecodable protocol.") - guard try next() else { - return nil - } - return try rootType!.init(from: decoder) - } - - /// Get all selected objects according to the `CodingTableKey`. - /// - /// - Returns: Table decodable objects according to the `CodingTableKey` - /// - Throws: `Error` - public func allObjects() throws -> [Any] { - let rootType = keys[0].rootType as? TableDecodableBase.Type - assert(rootType != nil, "\(keys[0].rootType) must conform to TableDecodable protocol.") - var objects: [Any] = [] - while try next() { - objects.append(try rootType!.init(from: decoder)) - } - return objects - } - - /// Get next selected object with type. You can do an iteration using it. - /// - /// - Parameter type: Type of table decodable object - /// - Returns: Table decodable object. Nil means the end of iteration. - /// - Throws: `Error` - public func nextObject(of type: Object.Type = Object.self) throws -> Object? { - assert(keys is [Object.CodingKeys], "Properties must belong to \(Object.self).CodingKeys.") - guard try next() else { - return nil - } - return try Object.init(from: decoder) - } - - /// Get all selected objects. - /// - /// - Parameter type: Type of table decodable object - /// - Returns: Table decodable objects. - /// - Throws: `Error` - public func allObjects(of type: Object.Type = Object.self) throws -> [Object] { - assert(keys is [Object.CodingKeys], "Properties must belong to \(Object.self).CodingKeys.") - var objects: [Object] = [] - while try next() { - objects.append(try Object.init(from: decoder)) - } - return objects - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Selectable.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Selectable.swift deleted file mode 100644 index 920b9373..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Selectable.swift +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public class Selectable { - private final var core: Core - final var optionalRecyclableHandleStatement: RecyclableHandleStatement? - final var statement: StatementSelect - - init(with core: Core, statement: StatementSelect) { - self.statement = statement - self.core = core - } - - deinit { - try? finalize() - } - - final func finalize() throws { - if let recyclableHandleStatement = optionalRecyclableHandleStatement { - try recyclableHandleStatement.raw.finalize() - optionalRecyclableHandleStatement = nil - } - } - - final func lazyHandleStatement() throws -> HandleStatement { - if optionalRecyclableHandleStatement == nil { - optionalRecyclableHandleStatement = try core.prepare(statement) - } - return optionalRecyclableHandleStatement!.raw - } - - //Since `next()` may throw errors, it can't conform to `Sequence` protocol to fit a `for in` loop. - @discardableResult - public final func next() throws -> Bool { - do { - return try lazyHandleStatement().step() - } catch let error { - try? finalize() - throw error - } - } - - /// WINQ interface - /// - /// - Parameter condition: Expression convertible - /// - Returns: `self` - @discardableResult - public final func `where`(_ condition: Condition) -> Self { - statement.where(condition) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public final func order(by orderConvertibleList: OrderBy...) -> Self { - return order(by: orderConvertibleList) - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public final func order(by orderConvertibleList: [OrderBy]) -> Self { - statement.order(by: orderConvertibleList) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameters: - /// - begin: Expression convertible - /// - end: Expression convertible - /// - Returns: `self` - @discardableResult - public final func limit(from begin: Limit, to end: Limit) -> Self { - statement.limit(from: begin, to: end) - return self - } - - @discardableResult - public final func limit(_ expressionConvertibleLimit: Limit) -> Self { - statement.limit(expressionConvertibleLimit) - return self - } - - @discardableResult - public final func limit(_ expressionConvertibleLimit: Limit, offset expressionConvertibleOffset: Offset) -> Self { - statement.limit(expressionConvertibleLimit, offset: expressionConvertibleOffset) - return self - } - - @discardableResult - public final func group(by expressionConvertibleGroupList: GroupBy...) -> Self { - return group(by: expressionConvertibleGroupList) - } - - @discardableResult - public final func group(by expressionConvertibleGroupList: [GroupBy]) -> Self { - statement.group(by: expressionConvertibleGroupList) - return self - } - - @discardableResult - public final func having(_ expressionConvertibleHaving: Having) -> Self { - statement.having(expressionConvertibleHaving) - return self - } -} - -extension Selectable: CoreRepresentable { - /// The tag of the related database. - public final var tag: Tag? { - return core.tag - } - - /// The path of the related database. - public final var path: String { - return core.path - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Table.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Table.swift deleted file mode 100644 index ed14e19a..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Table.swift +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// Convenient table interface -public final class Table { - private let database: Database - - /// Table name - public let name: String - - /// Table related type - public var rootType: Root.Type { - return Root.self - } - - init(withDatabase database: Database, named name: String, of type: Root.Type = Root.self) { - self.database = database - self.name = name - } -} - -extension Table: CoreRepresentable { - public typealias Object = Root - - /// The tag of the related database. - public var tag: Tag? { - return database.tag - } - - /// The path of the related database. - public var path: String { - return database.path - } -} - -extension Table: InsertTableInterface { - - /// Execute inserting with `TableCodable` object on specific(or all) properties - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Throws: `Error` - public func insert(objects: [Object], on propertyConvertibleList: [PropertyConvertible]? = nil) throws { - let insert = try Insert(with: self.database, named: self.name, on: propertyConvertibleList, isReplace: false) - return try insert.execute(with: objects) - } - - /// Execute inserting or replacing with `TableCodable` object on specific(or all) properties. - /// It will replace the original row while they have same primary key or row id. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Throws: `Error` - public func insertOrReplace(objects: [Object], on propertyConvertibleList: [PropertyConvertible]? = nil) throws { - let insert = try Insert(with: self.database, named: self.name, on: propertyConvertibleList, isReplace: true) - return try insert.execute(with: objects) - } - - /// Execute inserting with `TableCodable` object on specific(or all) properties - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Throws: `Error` - public func insert(objects: Object..., on propertyConvertibleList: [PropertyConvertible]? = nil) throws { - return try insert(objects: objects, on: propertyConvertibleList) - } - - /// Execute inserting or replacing with `TableCodable` object on specific(or all) properties. - /// It will replace the original row while they have same primary key or row id. - /// - /// Note that it will run embedded transaction while objects.count>1. - /// The embedded transaction means that it will run a transaction if it's not in other transaction, - /// otherwise it will be executed within the existing transaction. - /// - /// - Parameters: - /// - objects: Table encodable object - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - Throws: `Error` - public func insertOrReplace(objects: Object..., on propertyConvertibleList: [PropertyConvertible]? = nil) throws { - return try insertOrReplace(objects: objects, on: propertyConvertibleList) - } -} - -extension Table: UpdateTableInterface { - - /// Execute updating with `TableCodable` object on specific(or all) properties. - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - public func update(on propertyConvertibleList: [PropertyConvertible], - with object: Object, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let update = try Update(with: self.database, on: propertyConvertibleList, andTable: self.name) - if condition != nil { - update.where(condition!) - } - if orderList != nil { - update.order(by: orderList!) - } - if limit != nil { - if offset != nil { - update.limit(limit!, offset: offset!) - } else { - update.limit(limit!) - } - } - return try update.execute(with: object) - } - - /// Execute updating with `TableCodable` object on specific(or all) properties. - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - public func update(on propertyConvertibleList: PropertyConvertible..., - with object: Object, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - return try update(on: propertyConvertibleList, - with: object, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - /// Execute updating with row on specific(or all) properties. - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - public func update(on propertyConvertibleList: PropertyConvertible..., - with row: [ColumnEncodable], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - return try update(on: propertyConvertibleList, - with: row, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - /// Execute updating with row on specific(or all) properties. - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - object: Table encodable object - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - public func update(on propertyConvertibleList: [PropertyConvertible], - with row: [ColumnEncodable], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let update = try Update(with: self.database, on: propertyConvertibleList, andTable: self.name) - if condition != nil { - update.where(condition!) - } - if orderList != nil { - update.order(by: orderList!) - } - if limit != nil { - if offset != nil { - update.limit(limit!, offset: offset!) - } else { - update.limit(limit!) - } - } - return try update.execute(with: row) - } -} - -extension Table: DeleteTableInterface { - - /// Execute deleting - /// - /// - Parameters: - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Throws: `Error` - public func delete(where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws { - let delete = try Delete(with: self.database, andTableName: self.name) - if condition != nil { - delete.where(condition!) - } - if orderList != nil { - delete.order(by: orderList!) - } - if limit != nil { - if offset != nil { - delete.limit(limit!, offset: offset!) - } else { - delete.limit(limit!) - } - } - return try delete.execute() - } -} - -extension Table: SelectTableInterface { - - /// Get objects on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - public func getObjects(on propertyConvertibleList: [PropertyConvertible], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> [Object] { - let select = try Select(with: self.database, on: propertyConvertibleList, table: self.name, isDistinct: false) - if condition != nil { - select.where(condition!) - } - if orderList != nil { - select.order(by: orderList!) - } - if limit != nil { - if offset != nil { - select.limit(limit!, offset: offset!) - } else { - select.limit(limit!) - } - } - return try select.allObjects() - } - - /// Get objects on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - public func getObjects(on propertyConvertibleList: PropertyConvertible..., - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> [Object] { - return try getObjects(on: propertyConvertibleList.isEmpty ? Object.Properties.all : propertyConvertibleList, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - /// Get object on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - public func getObject(on propertyConvertibleList: [PropertyConvertible], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> Object? { - return try getObjects(on: propertyConvertibleList, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first - } - - /// Get object on specific(or all) properties - /// - /// - Parameters: - /// - propertyConvertibleList: `Property` or `CodingTableKey` list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: Table decodable objects - /// - Throws: `Error` - public func getObject(on propertyConvertibleList: PropertyConvertible..., - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> Object? { - return try getObjects(on: propertyConvertibleList.isEmpty ? Object.Properties.all : propertyConvertibleList, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first - } -} - -extension Table: RowSelectTableInterface { - - /// Get rows by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - public func getRows(on columnResultConvertibleList: [ColumnResultConvertible], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalRowXColumn { - let rowSelect = try RowSelect(with: self.database, - results: columnResultConvertibleList, - tables: [self.name], - isDistinct: false) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allRows() - } - - /// Get rows by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - public func getRows(on columnResultConvertibleList: ColumnResultConvertible..., - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalRowXColumn { - return try getRows(on: columnResultConvertibleList.isEmpty ? [Column.all] : columnResultConvertibleList, - where: condition, - orderBy: orderList, - limit: limit, - offset: offset) - } - - /// Get row by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - public func getRow(on columnResultConvertibleList: ColumnResultConvertible..., - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> FundamentalRow { - return try getRows(on: columnResultConvertibleList.isEmpty ? [Column.all] : columnResultConvertibleList, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first ?? [] - } - - /// Get row by specific selecting - /// - /// - Parameters: - /// - columnResultConvertibleList: WINQ column result list - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalRowXColumn` - /// - Throws: `Error` - public func getRow(on columnResultConvertibleList: [ColumnResultConvertible], - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - offset: Offset? = nil) throws -> FundamentalRow { - return try getRows(on: columnResultConvertibleList, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first ?? [] - } - - /// Get column by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalColumn` - /// - Throws: `Error` - public func getColumn(on result: ColumnResultConvertible, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalColumn { - let rowSelect = try RowSelect(with: self.database, results: [result], tables: [self.name], isDistinct: false) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allValues() - } - - /// Get distinct column by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `FundamentalColumn` - /// - Throws: `Error` - public func getDistinctColumn(on result: ColumnResultConvertible, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalColumn { - let rowSelect = try RowSelect(with: self.database, results: [result], tables: [self.name], isDistinct: true) - if condition != nil { - rowSelect.where(condition!) - } - if orderList != nil { - rowSelect.order(by: orderList!) - } - if limit != nil { - if offset != nil { - rowSelect.limit(limit!, offset: offset!) - } else { - rowSelect.limit(limit!) - } - } - return try rowSelect.allValues() - } - - /// Get value by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalValue` - /// - Throws: `Error` - public func getValue(on result: ColumnResultConvertible, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalValue { - return (try getRows(on: result, - where: condition, - orderBy: orderList, - limit: 1, - offset: offset).first?.first) ?? FundamentalValue(nil) - } - - /// Get distinct value by specific selecting - /// - /// - Parameters: - /// - columnResultConvertible: WINQ column result - /// - condition: Expression convertible - /// - orderList: Order convertible list - /// - offset: Expression convertible - /// - Returns: `FundamentalValue` - /// - Throws: `Error` - public func getDistinctValue(on result: ColumnResultConvertible, - where condition: Condition? = nil, - orderBy orderList: [OrderBy]? = nil, - limit: Limit? = nil, - offset: Offset? = nil) throws -> FundamentalValue { - return (try getDistinctColumn(on: result).first) ?? FundamentalValue(nil) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/TableInterface.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/TableInterface.swift deleted file mode 100644 index 21faf606..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/TableInterface.swift +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol InsertTableInterface: AnyObject { - associatedtype Object: TableEncodable - - func insert(objects: Object..., on propertyConvertibleList: [PropertyConvertible]?) throws - func insert(objects: [Object], on propertyConvertibleList: [PropertyConvertible]?) throws - func insertOrReplace(objects: Object..., on propertyConvertibleList: [PropertyConvertible]?) throws - func insertOrReplace(objects: [Object], on propertyConvertibleList: [PropertyConvertible]?) throws -} - -public protocol UpdateTableInterface: AnyObject { - associatedtype Object: TableEncodable - - func update(on propertyConvertibleList: PropertyConvertible..., - with object: Object, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - func update(on propertyConvertibleList: [PropertyConvertible], - with object: Object, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - func update(on propertyConvertibleList: PropertyConvertible..., - with row: [ColumnEncodable], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws - func update(on propertyConvertibleList: [PropertyConvertible], - with row: [ColumnEncodable], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -} - -public protocol DeleteTableInterface: AnyObject { - func delete(where condition: Condition?, orderBy orderList: [OrderBy]?, limit: Limit?, offset: Offset?) throws -} - -public protocol RowSelectTableInterface: AnyObject { - func getRows(on columnResultConvertibleList: [ColumnResultConvertible], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalRowXColumn - func getRows(on columnResultConvertibleList: ColumnResultConvertible..., - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalRowXColumn - - func getRow(on columnResultConvertibleList: ColumnResultConvertible..., - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> FundamentalRow - func getRow(on columnResultConvertibleList: [ColumnResultConvertible], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> FundamentalRow - - func getColumn(on result: ColumnResultConvertible, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalColumn - func getDistinctColumn(on result: ColumnResultConvertible, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalColumn - - func getValue(on result: ColumnResultConvertible, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalValue - func getDistinctValue(on result: ColumnResultConvertible, - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> FundamentalValue -} - -public protocol SelectTableInterface: AnyObject { - associatedtype Object: TableDecodable - - //TODO: Add generic property convertible to fit the type - func getObjects(on propertyConvertibleList: [PropertyConvertible], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> [Object] - func getObjects(on propertyConvertibleList: PropertyConvertible..., - where condition: Condition?, - orderBy orderList: [OrderBy]?, - limit: Limit?, - offset: Offset?) throws -> [Object] - - func getObject(on propertyConvertibleList: [PropertyConvertible], - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> Object? - func getObject(on propertyConvertibleList: PropertyConvertible..., - where condition: Condition?, - orderBy orderList: [OrderBy]?, - offset: Offset?) throws -> Object? -} diff --git a/Example/Pods/WCDB.swift/swift/source/core/interface/Update.swift b/Example/Pods/WCDB.swift/swift/source/core/interface/Update.swift deleted file mode 100644 index 9a6daeba..00000000 --- a/Example/Pods/WCDB.swift/swift/source/core/interface/Update.swift +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -/// The chain call for updating -public final class Update { - private var core: Core - private let statement = StatementUpdate() - private let keys: [CodingTableKeyBase] - - /// The number of changed rows in the most recent call. - /// It should be called after executing successfully - public var changes: Int? - - init(with core: Core, on propertyConvertibleList: [PropertyConvertible], andTable table: String) throws { - guard propertyConvertibleList.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .update, - code: .misuse, - message: "Updating \(table) with empty property") - } - guard table.count > 0 else { - throw Error.reportInterface(tag: core.tag, - path: core.path, - operation: .update, - code: .misuse, - message: "Nil table name") - } - self.keys = propertyConvertibleList.asCodingTableKeys() - self.core = core - self.statement - .update(table: table) - .set(propertyConvertibleList.map { (propertyConvertible) -> StatementUpdate.ValueType in - return (propertyConvertible, Expression.bindParameter) - }) - } - - /// WINQ interface for SQL - /// - /// - Parameter condition: Expression convertible - /// - Returns: `self` - @discardableResult - public func `where`(_ condition: Condition) -> Update { - statement.where(condition) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public func order(by orderList: OrderBy...) -> Update { - statement.order(by: orderList) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter orderList: Order convertible list - /// - Returns: `self` - @discardableResult - public func order(by orderList: [OrderBy]) -> Update { - statement.order(by: orderList) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameters: - /// - begin: Expression convertible - /// - end: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(from begin: Limit, to end: Limit) -> Update { - statement.limit(from: begin, to: end) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameter limit: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(_ limit: Limit) -> Update { - statement.limit(limit) - return self - } - - /// WINQ interface for SQL - /// - /// - Parameters: - /// - limit: Expression convertible - /// - offset: Expression convertible - /// - Returns: `self` - @discardableResult - public func limit(_ limit: Limit, offset: Offset) -> Update { - statement.limit(limit, offset: offset) - return self - } - - /// Execute the update chain call with object. - /// - /// - Parameter object: Table encodable object - /// - Throws: `Error` - public func execute(with object: Object) throws { - let recyclableHandleStatement: RecyclableHandleStatement = try core.prepare(statement) - let handleStatement = recyclableHandleStatement.raw - let encoder = TableEncoder(keys, on: recyclableHandleStatement) - try object.encode(to: encoder) - try handleStatement.step() - changes = handleStatement.changes - } - - /// Execute the update chain call with row. - /// - /// - Parameter row: Column encodable row - /// - Throws: `Error` - public func execute(with row: [ColumnEncodable?]) throws { - let recyclableHandleStatement: RecyclableHandleStatement = try core.prepare(statement) - let handleStatement = recyclableHandleStatement.raw - for (index, value) in row.enumerated() { - let bindingIndex = index + 1 - if let archivedValue = value?.archivedValue() { - handleStatement.bind(archivedValue, toIndex: bindingIndex) - } else { - handleStatement.bind(nil, toIndex: bindingIndex) - } - } - try handleStatement.step() - changes = handleStatement.changes - } -} - -extension Update: CoreRepresentable { - - /// The tag of the related database. - public var tag: Tag? { - return core.tag - } - - /// The path of the related database. - public var path: String { - return core.path - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Atomic.swift b/Example/Pods/WCDB.swift/swift/source/util/Atomic.swift deleted file mode 100644 index cd3edc8f..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Atomic.swift +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation -final class Atomic { - var raw: Value - let spin = Spin() - - init(_ raw: Value) { - self.raw = raw - } - - var value: Value { - spin.lock(); defer { spin.unlock() } - return raw - } - - func withValue(_ closure: (Value) -> Value) { - spin.lock(); defer { spin.unlock() } - raw = closure(raw) - } - - func assign(_ newValue: Value) { - spin.lock(); defer { spin.unlock() } - self.raw = newValue - } -} - -extension Atomic where Value==Int { - static func += (left: Atomic, right: Value) { - left.withValue { (value) -> Value in - return value + right - } - } - - static func -= (left: Atomic, right: Value) { - left.withValue { (value) -> Value in - return value - right - } - } - - static prefix func ++ (atomic: Atomic) -> Value { - var newValue: Value = 0 - atomic.withValue { (value) -> Value in - newValue = value + 1 - return newValue - } - return newValue - } -} - -extension Atomic where Value: Equatable { - static func == (left: Atomic, right: Value) -> Bool { - return left.value == right - } -} - -extension Atomic where Value: Comparable { - static func < (left: Atomic, right: Value) -> Bool { - return left.value < right - } - static func > (left: Atomic, right: Value) -> Bool { - return left.value > right - } -} - -extension Atomic where Value: OptionalRepresentable { - convenience init() { - self.init(Value.`nil`) - } -} - -extension Atomic: CustomStringConvertible { - var description: String { - return "\(value)" - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/ConcurrentList.swift b/Example/Pods/WCDB.swift/swift/source/util/ConcurrentList.swift deleted file mode 100644 index 46eb5194..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/ConcurrentList.swift +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class ConcurrentList { - var values: [Value] = [] - let capacityCap: Int - let spin = Spin() - - init(withCapacityCap capacityCap: Int) { - self.capacityCap = capacityCap - } - - func pushBack(_ value: Value) -> Bool { - spin.lock(); defer { spin.unlock() } - if values.count < capacityCap { - values.append(value) - return true - } - return false - } - - func popBack() -> Value? { - spin.lock(); defer { spin.unlock() } - if !values.isEmpty { - return values.removeLast() - } - return nil - } - - func clear() -> Int { - spin.lock(); defer { spin.unlock() } - let count = values.count - values.removeAll() - return count - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Convenience.swift b/Example/Pods/WCDB.swift/swift/source/util/Convenience.swift deleted file mode 100644 index fa42e9dc..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Convenience.swift +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -extension Array { - func joined(_ map: (Element) -> String, separateBy separator: String = ", ") -> String { - var flag = false - return reduce(into: "") { (output, element) in - if flag { - output.append(separator) - } else { - flag = true - } - output.append(map(element)) - } - } -} - -extension Array where Element: StringProtocol { - func joined(separateBy separator: String = ", ") -> String { - var flag = false - return reduce(into: "") { (output, element) in - if flag { - output.append(separator) - } else { - flag = true - } - output.append(String(element)) - } - } -} - -extension Array where Element: Describable { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.description }, separateBy: separator) - } -} - -extension Array where Element==ColumnResultConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asColumnResult().description }, separateBy: separator) - } -} - -extension Array where Element==ExpressionConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asExpression().description }, separateBy: separator) - } -} - -extension Array where Element==ColumnConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asColumn().description }, separateBy: separator) - } -} - -extension Array where Element==TableOrSubqueryConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asTableOrSubquery().description }, separateBy: separator) - } -} - -extension Array where Element==OrderConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asOrder().description }, separateBy: separator) - } -} - -extension Array where Element==ColumnIndexConvertible { - func joined(separateBy separator: String = ", ") -> String { - return joined({ $0.asIndex().description }, separateBy: separator) - } - - func asIndexes() -> [ColumnIndex] { - return map { $0.asIndex() } - } -} - -extension Array where Element==PropertyConvertible { - func asCodingTableKeys() -> [CodingTableKeyBase] { - return reduce(into: [CodingTableKeyBase]()) { (result, element) in - result.append(element.codingTableKey) - } - } -} - -extension Array { - mutating func expand(toNewSize newSize: Int, fillWith value: Iterator.Element) { - if count < newSize { - append(contentsOf: repeatElement(value, count: count.distance(to: newSize))) - } - } -} - -extension Array where Iterator.Element: FixedWidthInteger { - mutating func expand(toNewSize newSize: Int) { - expand(toNewSize: newSize, fillWith: 0) - } -} - -extension Dictionary { - func joined(_ map: (Key, Value) -> String, separateBy separator: String = "," ) -> String { - var flag = false - return reduce(into: "", { (output, arg) in - if flag { - output.append(separator) - } else { - flag = true - } - output.append(map(arg.key, arg.value)) - }) - } -} - -extension String { - var lastPathComponent: String { - return URL(fileURLWithPath: self).lastPathComponent - } - - func stringByAppending(pathComponent: String) -> String { - return URL(fileURLWithPath: self).appendingPathComponent(pathComponent).path - } - - var cString: UnsafePointer? { - return UnsafePointer((self as NSString).utf8String) - } - - init?(bytes: UnsafeRawPointer, count: Int, encoding: String.Encoding) { - self.init(data: Data(bytes: bytes, count: count), encoding: encoding) - } - - func range(from begin: Int, to end: Int) -> Range { - return index(startIndex, offsetBy: begin).. Range { - return range(from: location, to: location + length) - } -} - -extension Bool { - @inline(__always) func toInt32() -> Int32 { - return self ? 1 : 0 - } -} - -extension Int { - @inline(__always) func toInt64() -> Int64 { - return Int64(self) - } -} - -extension Int8 { - @inline(__always) func toInt32() -> Int32 { - return Int32(self) - } -} - -extension Int16 { - @inline(__always) func toInt32() -> Int32 { - return Int32(self) - } -} - -extension Int32 { - @inline(__always) func toBool() -> Bool { - return self != 0 - } - @inline(__always) func toInt8() -> Int8 { - return Int8(truncatingIfNeeded: self) - } - @inline(__always) func toInt16() -> Int16 { - return Int16(truncatingIfNeeded: self) - } - @inline(__always) func toUInt8() -> UInt8 { - return UInt8(bitPattern: Int8(truncatingIfNeeded: self)) - } - @inline(__always) func toUInt16() -> UInt16 { - return UInt16(bitPattern: Int16(truncatingIfNeeded: self)) - } - @inline(__always) func toUInt32() -> UInt32 { - return UInt32(bitPattern: self) - } -} - -extension Int64 { - @inline(__always) func toInt() -> Int { - return Int(truncatingIfNeeded: self) - } - @inline(__always) func toUInt() -> UInt { - return UInt(bitPattern: Int(truncatingIfNeeded: self)) - } - @inline(__always) func toUInt64() -> UInt64 { - return UInt64(bitPattern: self) - } -} - -extension UInt { - @inline(__always) func toInt64() -> Int64 { - return Int64(bitPattern: UInt64(self)) - } -} - -extension UInt8 { - @inline(__always) func toInt32() -> Int32 { - return Int32(bitPattern: UInt32(self)) - } -} - -extension UInt16 { - @inline(__always) func toInt32() -> Int32 { - return Int32(bitPattern: UInt32(self)) - } -} - -extension UInt32 { - @inline(__always) func toInt32() -> Int32 { - return Int32(bitPattern: self) - } -} - -extension UInt64 { - @inline(__always) func toInt64() -> Int64 { - return Int64(bitPattern: self) - } -} - -extension Float { - @inline(__always) func toDouble() -> Double { - return Double(self) - } -} - -extension Double { - @inline(__always) func toFloat() -> Float { - return Float(self) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Error.swift b/Example/Pods/WCDB.swift/swift/source/util/Error.swift deleted file mode 100644 index 225a1fb0..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Error.swift +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public struct ErrorValue { - public enum ErrorValueType { - case int - case string - } - private let value: Any - public let type: ErrorValueType - - init(_ value: String) { - self.value = value - self.type = .string - } - - init(_ value: Int) { - self.value = value - self.type = .int - } - - public var intValue: Int { - switch type { - case .int: - return value as! Int - case .string: - return Int(value as! String) ?? 0 - } - } - - public var stringValue: String { - switch type { - case .int: - return String(value as! Int) - case .string: - return value as! String - } - } -} - -public final class Error: Swift.Error, CustomStringConvertible { - public enum Key: Int, CustomStringConvertible { - case tag = 1 - case operation = 2 - case extendedCode = 3 - case message = 4 - case SQL = 5 - case path = 6 - - public var description: String { - switch self { - case .tag: - return "Tag" - case .operation: - return "Operation" - case .extendedCode: - return "ExtendedCode" - case .message: - return "Message" - case .SQL: - return "SQL" - case .path: - return "Path" - } - } - } - - public enum ErrorType: Int, CustomStringConvertible { - case sqlite = 1 - case systemCall = 2 - case core = 3 - case interface = 4 - case warning = 6 - case sqliteGlobal = 7 - case repair = 8 - - public var description: String { - switch self { - case .sqlite: - return "SQLite" - case .systemCall: - return "SystemCall" - case .core: - return "Core" - case .interface: - return "Interface" - case .warning: - return "Warning" - case .sqliteGlobal: - return "SQLiteGlobal" - case .repair: - return "Repair" - } - } - } - - public enum Operation { - public enum HandleOperation: Int { - case open = 1 - case close = 2 - case prepare = 3 - case exec = 4 - case step = 5 - case finalize = 6 - case setCipherKey = 7 - case isTableExists = 8 - } - - public enum InterfaceOperation: Int { - case handleStatement = 1 - case insert = 2 - case update = 3 - case select = 4 - case table = 5 - case chainCall = 6 - case delete = 7 - } - - public enum CoreOperation: Int { - case prepare = 1 - case exec = 2 - case begin = 3 - case commit = 4 - case rollback = 5 - case getThreadedHandle = 6 - case flowOut = 7 - case tokenize = 8 - case encode = 9 - case decode = 10 - case getPool = 11 - } - - public enum SystemCallOperation: Int { - case remove = 257 // 1 + 1<<8 Swift not supported - case link = 258 - case createDirectory = 259 - case getFileSize = 260 - case getAttributes = 261 - case setAttributes = 262 - } - - public enum RepairOperation: Int { - case saveMaster - case loadMaster - case repair - } - - case handle(HandleOperation) - case interface(InterfaceOperation) - case core(CoreOperation) - case systemCall(SystemCallOperation) - case repair(RepairOperation) - - public var value: Int { - switch self { - case .handle(let value): - return value.rawValue - case .interface(let value): - return value.rawValue - case .core(let value): - return value.rawValue - case .systemCall(let value): - return value.rawValue - case .repair(let value): - return value.rawValue - } - } - } - - public enum Code { - public enum CoreCode: Int { - case misuse = 1 - case exceed = 2 - } - - public enum InterfaceCode: Int { - case ORM = 1 - case inconsistent = 2 - case misuse = 4 - } - - public enum GlobalCode: Int { - case warning = 1 - case abort = 2 - } - - case repair(Int) - case sqliteGlobal(Int) - case systemCall(Int) - case sqlite(Int) - case core(CoreCode) - case interface(InterfaceCode) - case global(GlobalCode) - - public var value: Int { - switch self { - case .repair(let value): - return value - case .sqliteGlobal(let value): - return value - case .systemCall(let value): - return value - case .sqlite(let value): - return value - case .core(let value): - return value.rawValue - case .interface(let value): - return value.rawValue - case .global(let value): - return value.rawValue - } - } - } - - public typealias Infos = [Error.Key: ErrorValue] - public let infos: Infos - - public let type: ErrorType - public let code: Error.Code - - private init(type: Error.ErrorType, code: Error.Code, infos: Infos) { - self.infos = infos - self.type = type - self.code = code - } - - public var tag: Tag? { - return infos[.tag]?.intValue - } - - public var operationValue: Int? { - return infos[.operation]?.intValue - } - - public var extendedCode: Int? { - return infos[.extendedCode]?.intValue - } - - public var message: String? { - return infos[.message]?.stringValue - } - - public var sql: String? { - return infos[.SQL]?.stringValue - } - - public var path: String? { - return infos[.path]?.stringValue - } - - public var description: String { - return "Code:\(code), Type:\(type.description), \(infos.joined({ "\($0.description):\($1.stringValue)" }))" - } - - static let threadedSlient = ThreadLocal(defaultTo: false) - - public typealias Reporter = (Error) -> Void - static private let defaultReporter: Reporter = { - switch $0.type { - case .sqliteGlobal: - debugPrint("[WCDB][DEBUG] \($0.description)") - case .warning: - print("[WCDB][WARNING] \($0.description)") - default: - print("[WCDB][ERROR] \($0.description)") - } - } - static private let reporter: Atomic = Atomic(defaultReporter) - - static public func setReporter(_ reporter: @escaping Reporter) { - Error.reporter.assign(reporter) - } - static public func setReporter(_: Void?) { - Error.reporter.assign(nil) - } - static public func resetReporter() { - Error.reporter.assign(defaultReporter) - } - - private func report() { - guard !Error.threadedSlient.value else { - return - } - Error.reporter.raw?(self) - } - - @discardableResult - static func report(type: ErrorType, - code: Error.Code, - infos: Error.Infos) -> Error { - let error = Error(type: type, code: code, infos: infos) - error.report() - return error - } - - @discardableResult - static func reportSQLite(tag: Tag?, - path: String, - operation: Error.Operation.HandleOperation, - extendedError: Int32? = nil, - sql: String? = nil, - code: Int32, - message: String) -> Error { - var infos = [ - Error.Key.operation: ErrorValue(operation.rawValue), - Error.Key.message: ErrorValue(message), - Error.Key.path: ErrorValue(path)] - if extendedError != nil { - infos[Error.Key.extendedCode] = ErrorValue(Int(extendedError!)) - } - if sql != nil { - infos[Error.Key.SQL] = ErrorValue(sql!) - } - if tag != nil { - infos[Error.Key.tag] = ErrorValue(tag!) - } - return Error.report(type: .sqlite, - code: .sqlite(Int(code)), - infos: infos) - } - - @discardableResult - static func reportCore(tag: Tag?, - path: String, - operation: Error.Operation.CoreOperation, - code: Error.Code.CoreCode, message: String) -> Error { - var infos = [ - Error.Key.operation: ErrorValue(operation.rawValue), - Error.Key.message: ErrorValue(message), - Error.Key.path: ErrorValue(path)] - if tag != nil { - infos[Error.Key.tag] = ErrorValue(tag!) - } - return Error.report(type: .core, - code: .core(code), - infos: infos) - } - - @discardableResult - static func reportInterface(tag: Tag?, - path: String, - operation: Error.Operation.InterfaceOperation, - code: Error.Code.InterfaceCode, message: String) -> Error { - var infos = [ - Error.Key.operation: ErrorValue(operation.rawValue), - Error.Key.message: ErrorValue(message), - Error.Key.path: ErrorValue(path)] - if tag != nil { - infos[Error.Key.tag] = ErrorValue(tag!) - } - return Error.report(type: .interface, - code: .interface(code), - infos: infos) - } - - @discardableResult - static func reportSystemCall(operation: Error.Operation.SystemCallOperation, - path: String, - errno: Int, - message: String) -> Error { - return Error.report(type: .systemCall, code: .systemCall(errno), infos: [ - Error.Key.operation: ErrorValue(operation.rawValue), - Error.Key.message: ErrorValue(message), - Error.Key.path: ErrorValue(path) - ]) - } - - @discardableResult - static func reportSQLiteGlobal(code: Int, - message: String) -> Error { - return Error.report(type: .sqliteGlobal, - code: .sqliteGlobal(code), - infos: [Error.Key.message: ErrorValue(message)] - ) - } - - @discardableResult - static func reportRepair(path: String, - operation: Error.Operation.RepairOperation, - code: Int) -> Error { - return Error.report(type: .repair, - code: .repair(code), - infos: [ - Error.Key.path: ErrorValue(path), - Error.Key.operation: ErrorValue(operation.rawValue)]) - } - - static func warning(_ message: String) { - Error.report(type: .warning, - code: .global(.warning), - infos: [Error.Key.message: ErrorValue(message)]) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/File.swift b/Example/Pods/WCDB.swift/swift/source/util/File.swift deleted file mode 100644 index c36db4e2..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/File.swift +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class File { - static func remove(files: [String]) throws { - let fileManager = FileManager.default - try files.forEach { (file) in - do { - if fileManager.fileExists(atPath: file) { - try FileManager.default.removeItem(atPath: file) - } - } catch let error as NSError { - throw Error.reportSystemCall(operation: .remove, - path: file, - errno: error.code, - message: error.localizedDescription) - } - } - } - - static func getSize(ofFiles files: [String]) throws -> UInt64 { - let fileManager = FileManager.default - return try files.reduce(into: 0, { (filesSize, file) in - do { - filesSize += (try fileManager.attributesOfItem(atPath: file)[.size] as? UInt64) ?? 0 - } catch let error as NSError { - throw Error.reportSystemCall(operation: .getFileSize, - path: file, - errno: error.code, - message: error.localizedDescription) - } - }) - } - - static func isExists(atPath path: String) -> Bool { - return FileManager.default.fileExists(atPath: path) - } - - static func hardlink(atPath source: String, toPath destination: String) throws { - do { - try FileManager.default.linkItem(atPath: source, toPath: destination) - } catch let error as NSError { - throw Error.reportSystemCall(operation: .link, - path: destination, - errno: error.code, - message: error.localizedDescription) - } - } - - static func createDirectoryWithIntermediateDirectories(atPath path: String) throws { - do { - try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) - } catch let error as NSError { - throw Error.reportSystemCall(operation: .createDirectory, - path: path, - errno: error.code, - message: error.localizedDescription) - } - } - -#if WCDB_IOS - static func addFirstUserAuthenticationFileProtection(atPath path: String) throws { - let fileManager = FileManager.default - guard fileManager.fileExists(atPath: path) else { - return - } - var attributes: [FileAttributeKey: Any]! - do { - attributes = try fileManager.attributesOfItem(atPath: path) - } catch let error as NSError { - throw Error.reportSystemCall(operation: .getAttributes, - path: path, - errno: error.code, - message: error.localizedDescription) - } - guard let fileProtection = attributes[.protectionKey] as? String, - (fileProtection == FileProtectionType.completeUntilFirstUserAuthentication.rawValue - || fileProtection == FileProtectionType.none.rawValue) else { - return - } - attributes[.protectionKey] = FileProtectionType.completeUntilFirstUserAuthentication.rawValue - do { - try fileManager.setAttributes(attributes, ofItemAtPath: path) - } catch let error as NSError { - throw Error.reportSystemCall(operation: .setAttributes, - path: path, - errno: error.code, - message: error.localizedDescription) - } - } -#endif //WCDB_IOS -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Lock.swift b/Example/Pods/WCDB.swift/swift/source/util/Lock.swift deleted file mode 100644 index 827e707d..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Lock.swift +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -protocol Lockable: AnyObject { - func lock() - func unlock() -} - -@available(iOS 10.0, OSX 10.12, watchOS 3.0, tvOS 10.0, *) -final class UnfairLock: Lockable { - private var unfairLock = os_unfair_lock_s() - - func lock() { - os_unfair_lock_lock(&unfairLock) - } - - func unlock() { - os_unfair_lock_unlock(&unfairLock) - } -} - -final class Mutex: Lockable { - private var mutex = pthread_mutex_t() - - init() { - pthread_mutex_init(&mutex, nil) - } - - deinit { - pthread_mutex_destroy(&mutex) - } - - func lock() { - pthread_mutex_lock(&mutex) - } - - func unlock() { - pthread_mutex_unlock(&mutex) - } -} - -final class RecursiveMutex: Lockable { - private var mutex = pthread_mutex_t() - - init() { - var attr = pthread_mutexattr_t() - pthread_mutexattr_init(&attr) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) - pthread_mutex_init(&mutex, &attr) - } - - deinit { - pthread_mutex_destroy(&mutex) - } - - func lock() { - pthread_mutex_lock(&mutex) - } - - func unlock() { - pthread_mutex_unlock(&mutex) - } -} - -final class Spin: Lockable { - private let locker: Lockable - - init() { - if #available(iOS 10.0, macOS 10.12, watchOS 3.0, tvOS 10.0, *) { - locker = UnfairLock() - } else { - locker = Mutex() - } - } - - func lock() { - locker.lock() - } - - func unlock() { - locker.unlock() - } -} - -final class ConditionLock: Lockable { - private var mutex = pthread_mutex_t() - private var cond = pthread_cond_t() - - init() { - pthread_mutex_init(&mutex, nil) - pthread_cond_init(&cond, nil) - } - - deinit { - pthread_cond_destroy(&cond) - pthread_mutex_destroy(&mutex) - } - - func lock() { - pthread_mutex_lock(&mutex) - } - - func unlock() { - pthread_mutex_unlock(&mutex) - } - - func wait() { - pthread_cond_wait(&cond, &mutex) - } - - func wait(timeout: TimeInterval) { - let integerPart = Int(timeout.nextDown) - let fractionalPart = timeout - Double(integerPart) - var ts = timespec(tv_sec: integerPart, tv_nsec: Int(fractionalPart * 1000000000)) - - pthread_cond_timedwait_relative_np(&cond, &mutex, &ts) - } - - func signal() { - pthread_cond_signal(&cond) - } -} - -extension DispatchQueue { - static private let spin = Spin() - static private var tracker: Set = [] - - static func once(name: String, _ block: () -> Void) { - spin.lock(); defer { spin.unlock() } - guard !tracker.contains(name) else { - return - } - block() - tracker.insert(name) - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Optional.swift b/Example/Pods/WCDB.swift/swift/source/util/Optional.swift deleted file mode 100644 index a28e5119..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Optional.swift +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -public protocol OptionalRepresentable { - associatedtype WrappedType - - static var `nil`: Self {get} -} - -extension Optional: OptionalRepresentable { - public static var `nil`: Wrapped? { - return nil - } - - public typealias WrappedType = Wrapped -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/RWLock.swift b/Example/Pods/WCDB.swift/swift/source/util/RWLock.swift deleted file mode 100644 index 23f8a973..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/RWLock.swift +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class RWLock { - var mutex = pthread_mutex_t() - var cond = pthread_cond_t() - var reader = 0 - var writer = 0 - var pending = 0 - - init() { - pthread_mutex_init(&mutex, nil) - pthread_cond_init(&cond, nil) - } - - deinit { - pthread_cond_destroy(&cond) - pthread_mutex_destroy(&mutex) - } - - func lockRead() { - pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } - while writer>0 || pending>0 { - pthread_cond_wait(&cond, &mutex) - } - reader += 1 - } - - func unlockRead() { - pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } - reader -= 1 - if reader == 0 { - pthread_cond_broadcast(&cond) - } - } - - func lockWrite() { - pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } - pending += 1 - while writer>0||reader>0 { - pthread_cond_wait(&cond, &mutex) - } - pending -= 1 - writer += 1 - } - - func unlockWrite() { - pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } - writer -= 1 - pthread_cond_broadcast(&cond) - } - - var isWriting: Bool { - pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } - return writer>0 - } - -// var isReading: Bool { -// pthread_mutex_lock(&mutex); defer { pthread_mutex_unlock(&mutex) } -// return reader>0 -// } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Recyclable.swift b/Example/Pods/WCDB.swift/swift/source/util/Recyclable.swift deleted file mode 100644 index 23c28c62..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Recyclable.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -//TODO: Refactor -class Recyclable { - typealias OnRecycled = () -> Void - let onRecycled: OnRecycled? - - final let raw: Value - - init(_ raw: Value, onRecycled: @escaping OnRecycled) { - self.raw = raw - self.onRecycled = onRecycled - } - - init(_ raw: Value) { - self.raw = raw - self.onRecycled = nil - } - - deinit { - if onRecycled != nil { - onRecycled!() - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.c b/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.c deleted file mode 100644 index 9b171da7..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 -#include - -int sqlite3_bind_text_transient(sqlite3_stmt *a, int b, const char *c, int d) -{ - return sqlite3_bind_text(a, b, c, d, SQLITE_TRANSIENT); -} - -int sqlite3_bind_blob_transient(sqlite3_stmt *a, int b, const void *c, int n) -{ - return sqlite3_bind_blob(a, b, c, n, SQLITE_TRANSIENT); -} - -int sqlite3_config_multithread(void) -{ - return sqlite3_config(SQLITE_CONFIG_MULTITHREAD); -} - -int sqlite3_config_memstatus(int a) -{ - return sqlite3_config(SQLITE_CONFIG_MEMSTATUS, a); -} - -int sqlite3_config_log(sqlite3_global_log a, void *b) -{ - return sqlite3_config(SQLITE_CONFIG_LOG, a, b); -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.h b/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.h deleted file mode 100644 index 5275c8e1..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 SQLite_Bridging_h -#define SQLite_Bridging_h - -#import -#import - -struct Tokenizer { - sqlite3_tokenizer base; - void *info; -}; -typedef struct Tokenizer Tokenizer; - -struct Cursor { - sqlite3_tokenizer_cursor base; - void *info; -}; -typedef struct Cursor Cursor; - -typedef struct sqlite3_stmt sqlite3_stmt; - -int sqlite3_bind_text_transient(sqlite3_stmt *, int, const char *, int); - -int sqlite3_bind_blob_transient(sqlite3_stmt *, int, const void *, int n); - -int sqlite3_config_multithread(void); - -int sqlite3_config_memstatus(int); - -typedef void (*sqlite3_global_log)(void *, int, const char *); - -int sqlite3_config_log(sqlite3_global_log, void *); - -#endif /* SQLite_Bridging_h */ diff --git a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.swift b/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.swift deleted file mode 100644 index 2ebcb159..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/SQLite-Bridging.swift +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -typealias SQLite3 = OpaquePointer -typealias SQLite3Statement = OpaquePointer -typealias SQLite3Value = OpaquePointer diff --git a/Example/Pods/WCDB.swift/swift/source/util/SteadyClock.swift b/Example/Pods/WCDB.swift/swift/source/util/SteadyClock.swift deleted file mode 100644 index 633a3f75..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/SteadyClock.swift +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -struct SteadyClock { - private var time: TimeInterval //monotonic - - init() { - time = ProcessInfo.processInfo.systemUptime - } - - private init(with time: TimeInterval) { - self.time = time - } - - static func >= (lhs: SteadyClock, rhs: SteadyClock) -> Bool { - return lhs.time >= rhs.time - } - - static func - (lhs: SteadyClock, rhs: SteadyClock) -> TimeInterval { - return lhs.time - rhs.time - } - - static func + (steadyClock: SteadyClock, timeInterval: TimeInterval) -> SteadyClock { - return SteadyClock(with: steadyClock.time + timeInterval) - } - - static func now() -> SteadyClock { - return SteadyClock() - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/Tagged.swift b/Example/Pods/WCDB.swift/swift/source/util/Tagged.swift deleted file mode 100644 index c8b22b8c..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/Tagged.swift +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class Counter { - static let counter = Atomic(0) - - static func step() -> Int { - return ++counter - } -} - -final class Tagged: Equatable { - let identifier: Int - let value: Value - - init(_ value: Value) { - self.value = value - self.identifier = Counter.step() - } - - static func == (lhs: Tagged, rhs: Tagged) -> Bool { - return lhs.identifier == rhs.identifier - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/ThreadLocal.swift b/Example/Pods/WCDB.swift/swift/source/util/ThreadLocal.swift deleted file mode 100644 index e6513db6..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/ThreadLocal.swift +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class ThreadLocal { - private final class Wrapper: RawRepresentable { - typealias RawValue = Value - var rawValue: RawValue - init(rawValue: RawValue) { - self.rawValue = rawValue - } - } - - private var key = pthread_key_t() - private let defaultValue: Value - - init(defaultTo defaultValue: Value) { - self.defaultValue = defaultValue - pthread_key_create(&key, { - Unmanaged.fromOpaque($0).release() - }) - } - - deinit { - pthread_key_delete(key) - } - - var value: Value { - get { - guard let pointer = pthread_getspecific(key) else { - return defaultValue - } - return Unmanaged.fromOpaque(pointer).takeUnretainedValue().rawValue - } - set { - if let pointer = pthread_getspecific(key) { - Unmanaged.fromOpaque(pointer).release() - } - pthread_setspecific(key, Unmanaged.passRetained(Wrapper(rawValue: newValue)).toOpaque()) - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/TimedQueue.swift b/Example/Pods/WCDB.swift/swift/source/util/TimedQueue.swift deleted file mode 100644 index 149b7548..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/TimedQueue.swift +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 Foundation - -final class TimedQueue { - typealias Element = (key: Key, clock: SteadyClock) - typealias List = ContiguousArray - typealias Map = [Key: List.Index] - - let delay: TimeInterval - - let conditionLock = ConditionLock() - - var list: List = [] - var map: Map = [:] - - init(withDelay delay: TimeInterval) { - self.delay = delay - } - - func remove(with key: Key) { - conditionLock.lock(); defer { conditionLock.unlock() } - - guard let index = map.index(forKey: key) else { - return - } - list.remove(at: map[index].value) - map.remove(at: index) - } - - func reQueue(with key: Key) { - conditionLock.lock(); defer { conditionLock.unlock() } - - let signal = list.isEmpty - - if let index = map.index(forKey: key) { - list.remove(at: map[index].value) - map.remove(at: index) - } - - list.append((key, SteadyClock.now()+delay)) - map[key] = list.startIndex - if signal { - conditionLock.signal() - } - } - - func wait(untilExpired onExpired: (Key) -> Void) { - while true { - var key: Key! - do { - conditionLock.lock(); defer { conditionLock.unlock() } - guard let element = list.first else { - conditionLock.wait() - continue - } - let now = SteadyClock.now() - guard now >= element.clock else { - conditionLock.wait(timeout: element.clock - now) - continue - } - key = element.key - list.removeFirst() - map.removeValue(forKey: key) - } - onExpired(key) - break - } - } -} diff --git a/Example/Pods/WCDB.swift/swift/source/util/WCDB-Bridging.h b/Example/Pods/WCDB.swift/swift/source/util/WCDB-Bridging.h deleted file mode 100644 index 1a06424a..00000000 --- a/Example/Pods/WCDB.swift/swift/source/util/WCDB-Bridging.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making - * WCDB available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. - * All rights reserved. - * - * Licensed under the BSD 3-Clause License (the "License"); you may not use - * this file except in compliance with the License. You may obtain a copy of - * the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * 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 diff --git a/Example/Pods/WCDBOptimizedSQLCipher/LICENSE b/Example/Pods/WCDBOptimizedSQLCipher/LICENSE deleted file mode 100644 index bebe1e7e..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2008, ZETETIC LLC -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of the ZETETIC LLC 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 ZETETIC LLC ''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 ZETETIC LLC 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. diff --git a/Example/Pods/WCDBOptimizedSQLCipher/README.md b/Example/Pods/WCDBOptimizedSQLCipher/README.md deleted file mode 100644 index 3d6e594d..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/README.md +++ /dev/null @@ -1,434 +0,0 @@ -## SQLCipher - -SQLCipher extends the [SQLite](https://www.sqlite.org) database library to add security enhancements that make it more suitable for encrypted local data storage such as on-the-fly encryption, tamper evidence, and key derivation. Based on SQLite, SQLCipher closely tracks SQLite and periodically integrates stable SQLite release features. - -SQLCipher is maintained by Zetetic, LLC, and additional information and documentation is available on the official [SQLCipher site](https://www.zetetic.net/sqlcipher/). - -## Features - -- Fast performance with as little as 5-15% overhead for encryption on many operations -- 100% of data in the database file is encrypted -- Good security practices (CBC mode, HMAC, key derivation) -- Zero-configuration and application level cryptography -- Algorithms provided by the peer reviewed OpenSSL crypto library. -- Configurable crypto providers - -## Compatibility - -SQLCipher maintains database format compatibility within the same major version number so an application on any platform can open databases created by any other application provided the major version of SQLCipher is the same between them. However, major version updates (e.g. from 3.x to 4.x) often include changes to default settings. This means that newer major versions of SQLCipher will not open databases created by older versions without using special settings. For example, SQLCipher 4 introduces many new performance and security enhancements. The new default algorithms, increased KDF iterations, and larger page size mean that SQLCipher 4 will not open databases created by SQLCipher 1.x, 2.x, or 3.x by default. Instead, an application would either need to migrate the older databases to use the new format or enable a special backwards-compatibility mode. The available options are described in SQLCipher's [upgrade documentation](https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283). - -SQLCipher is also compatible with standard SQLite databases. When a key is not provided, SQLCipher will behave just like the standard SQLite library. It is also possible to convert from a plaintext database (standard SQLite) to an encrypted SQLCipher database using [ATTACH and the sqlcipher_export() convenience function](https://discuss.zetetic.net/t/how-to-encrypt-a-plaintext-sqlite-database-to-use-sqlcipher-and-avoid-file-is-encrypted-or-is-not-a-database-errors/868). - -## Contributions - -The SQLCipher team welcomes contributions to the core library. All contributions including pull requests and patches should be based on the `prerelease` branch, and must be accompanied by a [contributor agreement](https://www.zetetic.net/contributions/). For large changes we strongly encourage [discussion](https://discuss.zetetic.net/c/sqlcipher) of the proposed change prior to development and submission. - -## Compiling - -Building SQLCipher is almost the same as compiling a regular version of -SQLite with two small exceptions: - - 1. You *must* define `SQLITE_HAS_CODEC` and `SQLITE_TEMP_STORE=2` when building sqlcipher. - 2. If compiling against the default OpenSSL crypto provider, you will need to link libcrypto - -Example Static linking (replace /opt/local/lib with the path to libcrypto.a). Note in this -example, `--enable-tempstore=yes` is setting `SQLITE_TEMP_STORE=2` for the build. - - $ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \ - LDFLAGS="/opt/local/lib/libcrypto.a" - $ make - -Example Dynamic linking - - $ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \ - LDFLAGS="-lcrypto" - $ make - -## Encrypting a database - -To specify an encryption passphrase for the database via the SQL interface you -use a pragma. The passphrase you enter is passed through PBKDF2 key derivation to -obtain the encryption key for the database - - PRAGMA key = 'passphrase'; - -Alternately, you can specify an exact byte sequence using a blob literal. If you -use this method it is your responsibility to ensure that the data you provide is a -64 character hex string, which will be converted directly to 32 bytes (256 bits) of -key data without key derivation. - - PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'"; - -To encrypt a database programmatically you can use the `sqlite3_key` function. -The data provided in `pKey` is converted to an encryption key according to the -same rules as `PRAGMA key`. - - int sqlite3_key(sqlite3 *db, const void *pKey, int nKey); - -`PRAGMA key` or `sqlite3_key` should be called as the first operation when a database is open. - -## Changing a database key - -To change the encryption passphrase for an existing database you may use the rekey pragma -after you've supplied the correct database password; - - PRAGMA key = 'passphrase'; -- start with the existing database passphrase - PRAGMA rekey = 'new-passphrase'; -- rekey will reencrypt with the new passphrase - -The hex rekey pragma may be used to rekey to a specific binary value - - PRAGMA rekey = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'"; - -This can be accomplished programmatically by using sqlite3_rekey; - - sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) - -## Support - -The primary avenue for support and discussions is the SQLCipher discuss site: - -https://discuss.zetetic.net/c/sqlcipher - -Issues or support questions on using SQLCipher should be entered into the -GitHub Issue tracker: - -https://github.com/sqlcipher/sqlcipher/issues - -Please DO NOT post issues, support questions, or other problems to blog -posts about SQLCipher as we do not monitor them frequently. - -If you are using SQLCipher in your own software please let us know at -support@zetetic.net! - -## License - -Copyright (c) 2016, ZETETIC LLC -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of the ZETETIC LLC 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 ZETETIC LLC ''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 ZETETIC LLC 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. - -# Begin SQLite README.md - -

SQLite Source Repository

- -This repository contains the complete source code for the -[SQLite database engine](https://sqlite.org/). Some test scripts -are also included. However, many other test scripts -and most of the documentation are managed separately. - -SQLite [does not use Git](https://sqlite.org/whynotgit.html). -If you are reading this on GitHub, then you are looking at an -unofficial mirror. See for the official -repository. - -## Obtaining The Code - -SQLite sources are managed using the -[Fossil](https://www.fossil-scm.org/), a distributed version control system -that was specifically designed to support SQLite development. -If you do not want to use Fossil, you can download tarballs or ZIP -archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows: - - * Lastest trunk check-in as - [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz), - [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or - [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar). - - * Latest release as - [Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release), - [ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or - [SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release). - - * For other check-ins, substitute an appropriate branch name or - tag or hash prefix for "release" in the URLs of the previous - bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline) - to locate the check-in desired, click on its information page link, - then click on the "Tarball" or "ZIP Archive" links on the information - page. - -If you do want to use Fossil to check out the source tree, -first install Fossil version 2.0 or later. -(Source tarballs and precompiled binaries available -[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is -a stand-alone program. To install, simply download or build the single -executable file and put that file someplace on your $PATH.) -Then run commands like this: - - mkdir ~/sqlite - cd ~/sqlite - fossil clone https://www.sqlite.org/src sqlite.fossil - fossil open sqlite.fossil - -After setting up a repository using the steps above, you can always -update to the lastest version using: - - fossil update trunk ;# latest trunk check-in - fossil update release ;# latest official release - -Or type "fossil ui" to get a web-based user interface. - -## Compiling - -First create a directory in which to place -the build products. It is recommended, but not required, that the -build directory be separate from the source directory. Cd into the -build directory and then from the build directory run the configure -script found at the root of the source tree. Then run "make". - -For example: - - tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" - mkdir bld ;# Build will occur in a sibling directory - cd bld ;# Change to the build directory - ../sqlite/configure ;# Run the configure script - make ;# Run the makefile. - make sqlite3.c ;# Build the "amalgamation" source file - make test ;# Run some tests (requires Tcl) - -See the makefile for additional targets. - -The configure script uses autoconf 2.61 and libtool. If the configure -script does not work out for you, there is a generic makefile named -"Makefile.linux-gcc" in the top directory of the source tree that you -can copy and edit to suit your needs. Comments on the generic makefile -show what changes are needed. - -## Using MSVC - -On Windows, all applicable build products can be compiled with MSVC. -First open the command prompt window associated with the desired compiler -version (e.g. "Developer Command Prompt for VS2013"). Next, use NMAKE -with the provided "Makefile.msc" to build one of the supported targets. - -For example: - - mkdir bld - cd bld - nmake /f Makefile.msc TOP=..\sqlite - nmake /f Makefile.msc sqlite3.c TOP=..\sqlite - nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite - nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite - nmake /f Makefile.msc test TOP=..\sqlite - -There are several build options that can be set via the NMAKE command -line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument -to the "sqlite3.dll" command line above. When debugging into the SQLite -code, adding the "DEBUG=1" argument to one of the above command lines is -recommended. - -SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation -is required by the makefiles (including those for MSVC). SQLite contains -a lot of generated code and Tcl is used to do much of that code generation. - -## Source Code Tour - -Most of the core source files are in the **src/** subdirectory. The -**src/** folder also contains files used to build the "testfixture" test -harness. The names of the source files used by "testfixture" all begin -with "test". -The **src/** also contains the "shell.c" file -which is the main program for the "sqlite3.exe" -[command-line shell](https://sqlite.org/cli.html) and -the "tclsqlite.c" file which implements the -[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite. -(Historical note: SQLite began as a Tcl -extension and only later escaped to the wild as an independent library.) - -Test scripts and programs are found in the **test/** subdirectory. -Addtional test code is found in other source repositories. -See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for -additional information. - -The **ext/** subdirectory contains code for extensions. The -Full-text search engine is in **ext/fts3**. The R-Tree engine is in -**ext/rtree**. The **ext/misc** subdirectory contains a number of -smaller, single-file extensions, such as a REGEXP operator. - -The **tool/** subdirectory contains various scripts and programs used -for building generated source code files or for testing or for generating -accessory programs such as "sqlite3_analyzer(.exe)". - -### Generated Source Code Files - -Several of the C-language source files used by SQLite are generated from -other sources rather than being typed in manually by a programmer. This -section will summarize those automatically-generated files. To create all -of the automatically-generated files, simply run "make target_source". -The "target_source" make target will create a subdirectory "tsrc/" and -fill it with all the source files needed to build SQLite, both -manually-edited files and automatically-generated files. - -The SQLite interface is defined by the **sqlite3.h** header file, which is -generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The -[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion. -The manifest.uuid file contains the SHA3 hash of the particular check-in -and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file -contains the current SQLite version number. The sqlite3.h header is really -just a copy of src/sqlite.h.in with the source-id and version number inserted -at just the right spots. Note that comment text in the sqlite3.h file is -used to generate much of the SQLite API documentation. The Tcl scripts -used to generate that documentation are in a separate source repository. - -The SQL language parser is **parse.c** which is generate from a grammar in -the src/parse.y file. The conversion of "parse.y" into "parse.c" is done -by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code -for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a -template for generating its parser. - -Lemon also generates the **parse.h** header file, at the same time it -generates parse.c. But the parse.h header file is -modified further (to add additional symbols) using the ./addopcodes.tcl -Tcl script. - -The **opcodes.h** header file contains macros that define the numbers -corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h -file is generated by the scanning the src/vdbe.c source file. The -Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h. -A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate -the **opcodes.c** source file, which contains a reverse mapping from -opcode-number to opcode-name that is used for EXPLAIN output. - -The **keywordhash.h** header file contains the definition of a hash table -that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into -the numeric codes used by the parse.c parser. The keywordhash.h file is -generated by a C-language program at tool mkkeywordhash.c. - -The **pragma.h** header file contains various definitions used to parse -and implement the PRAGMA statements. The header is generated by a -script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit -the **tool/mkpragmatab.tcl** file to insert the information needed by the -parser for your new PRAGMA, then run the script to regenerate the -**pragma.h** header file. - -### The Amalgamation - -All of the individual C source code and header files (both manually-edited -and automatically-generated) can be combined into a single big source file -**sqlite3.c** called "the amalgamation". The amalgamation is the recommended -way of using SQLite in a larger application. Combining all individual -source code files into a single big source code file allows the C compiler -to perform more cross-procedure analysis and generate better code. SQLite -runs about 5% faster when compiled from the amalgamation versus when compiled -from individual source files. - -The amalgamation is generated from the tool/mksqlite3c.tcl Tcl script. -First, all of the individual source files must be gathered into the tsrc/ -subdirectory (using the equivalent of "make target_source") then the -tool/mksqlite3c.tcl script is run to copy them all together in just the -right order while resolving internal "#include" references. - -The amalgamation source file is more than 200K lines long. Some symbolic -debuggers (most notably MSVC) are unable to deal with files longer than 64K -lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl, -can be run on the amalgamation to break it up into a single small C file -called **sqlite3-all.c** that does #include on about seven other files -named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-7.c**. In this way, -all of the source code is contained within a single translation unit so -that the compiler can do extra cross-procedure optimization, but no -individual source file exceeds 32K lines in length. - -## How It All Fits Together - -SQLite is modular in design. -See the [architectural description](http://www.sqlite.org/arch.html) -for details. Other documents that are useful in -(helping to understand how SQLite works include the -[file format](http://www.sqlite.org/fileformat2.html) description, -the [virtual machine](http://www.sqlite.org/opcode.html) that runs -prepared statements, the description of -[how transactions work](http://www.sqlite.org/atomiccommit.html), and -the [overview of the query planner](http://www.sqlite.org/optoverview.html). - -Years of effort have gone into optimizating SQLite, both -for small size and high performance. And optimizations tend to result in -complex code. So there is a lot of complexity in the current SQLite -implementation. It will not be the easiest library in the world to hack. - -Key files: - - * **sqlite.h.in** - This file defines the public interface to the SQLite - library. Readers will need to be familiar with this interface before - trying to understand how the library works internally. - - * **sqliteInt.h** - this header file defines many of the data objects - used internally by SQLite. In addition to "sqliteInt.h", some - subsystems have their own header files. - - * **parse.y** - This file describes the LALR(1) grammar that SQLite uses - to parse SQL statements, and the actions that are taken at each step - in the parsing process. - - * **vdbe.c** - This file implements the virtual machine that runs - prepared statements. There are various helper files whose names - begin with "vdbe". The VDBE has access to the vdbeInt.h header file - which defines internal data objects. The rest of SQLite interacts - with the VDBE through an interface defined by vdbe.h. - - * **where.c** - This file (together with its helper files named - by "where*.c") analyzes the WHERE clause and generates - virtual machine code to run queries efficiently. This file is - sometimes called the "query optimizer". It has its own private - header file, whereInt.h, that defines data objects used internally. - - * **btree.c** - This file contains the implementation of the B-Tree - storage engine used by SQLite. The interface to the rest of the system - is defined by "btree.h". The "btreeInt.h" header defines objects - used internally by btree.c and not published to the rest of the system. - - * **pager.c** - This file contains the "pager" implementation, the - module that implements transactions. The "pager.h" header file - defines the interface between pager.c and the rest of the system. - - * **os_unix.c** and **os_win.c** - These two files implement the interface - between SQLite and the underlying operating system using the run-time - pluggable VFS interface. - - * **shell.c.in** - This file is not part of the core SQLite library. This - is the file that, when linked against sqlite3.a, generates the - "sqlite3.exe" command-line shell. The "shell.c.in" file is transformed - into "shell.c" as part of the build process. - - * **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It - is not part of the core SQLite library. But as most of the tests in this - repository are written in Tcl, the Tcl language bindings are important. - - * **test*.c** - Files in the src/ folder that begin with "test" go into - building the "testfixture.exe" program. The testfixture.exe program is - an enhanced Tcl shell. The testfixture.exe program runs scripts in the - test/ folder to validate the core SQLite code. The testfixture program - (and some other test programs too) is build and run when you type - "make test". - - * **ext/misc/json1.c** - This file implements the various JSON functions - that are build into SQLite. - -There are many other source files. Each has a succinct header comment that -describes its purpose and role within the larger system. - - -## Contacts - -The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/) -with geographically distributed backups at -[http://www2.sqlite.org/](http://www2.sqlite.org) and -[http://www3.sqlite.org/](http://www3.sqlite.org). diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.c deleted file mode 100644 index bd0003d0..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.c +++ /dev/null @@ -1,6005 +0,0 @@ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is an SQLite module implementing full-text search. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ - -/* The full-text index is stored in a series of b+tree (-like) -** structures called segments which map terms to doclists. The -** structures are like b+trees in layout, but are constructed from the -** bottom up in optimal fashion and are not updatable. Since trees -** are built from the bottom up, things will be described from the -** bottom up. -** -** -**** Varints **** -** The basic unit of encoding is a variable-length integer called a -** varint. We encode variable-length integers in little-endian order -** using seven bits * per byte as follows: -** -** KEY: -** A = 0xxxxxxx 7 bits of data and one flag bit -** B = 1xxxxxxx 7 bits of data and one flag bit -** -** 7 bits - A -** 14 bits - BA -** 21 bits - BBA -** and so on. -** -** This is similar in concept to how sqlite encodes "varints" but -** the encoding is not the same. SQLite varints are big-endian -** are are limited to 9 bytes in length whereas FTS3 varints are -** little-endian and can be up to 10 bytes in length (in theory). -** -** Example encodings: -** -** 1: 0x01 -** 127: 0x7f -** 128: 0x81 0x00 -** -** -**** Document lists **** -** A doclist (document list) holds a docid-sorted list of hits for a -** given term. Doclists hold docids and associated token positions. -** A docid is the unique integer identifier for a single document. -** A position is the index of a word within the document. The first -** word of the document has a position of 0. -** -** FTS3 used to optionally store character offsets using a compile-time -** option. But that functionality is no longer supported. -** -** A doclist is stored like this: -** -** array { -** varint docid; (delta from previous doclist) -** array { (position list for column 0) -** varint position; (2 more than the delta from previous position) -** } -** array { -** varint POS_COLUMN; (marks start of position list for new column) -** varint column; (index of new column) -** array { -** varint position; (2 more than the delta from previous position) -** } -** } -** varint POS_END; (marks end of positions for this document. -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. A "position" is an index of a token in the token stream -** generated by the tokenizer. Note that POS_END and POS_COLUMN occur -** in the same logical place as the position element, and act as sentinals -** ending a position list array. POS_END is 0. POS_COLUMN is 1. -** The positions numbers are not stored literally but rather as two more -** than the difference from the prior position, or the just the position plus -** 2 for the first position. Example: -** -** label: A B C D E F G H I J K -** value: 123 5 9 1 1 14 35 0 234 72 0 -** -** The 123 value is the first docid. For column zero in this document -** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 -** at D signals the start of a new column; the 1 at E indicates that the -** new column is column number 1. There are two positions at 12 and 45 -** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The -** 234 at I is the delta to next docid (357). It has one position 70 -** (72-2) and then terminates with the 0 at K. -** -** A "position-list" is the list of positions for multiple columns for -** a single docid. A "column-list" is the set of positions for a single -** column. Hence, a position-list consists of one or more column-lists, -** a document record consists of a docid followed by a position-list and -** a doclist consists of one or more document records. -** -** A bare doclist omits the position information, becoming an -** array of varint-encoded docids. -** -**** Segment leaf nodes **** -** Segment leaf nodes store terms and doclists, ordered by term. Leaf -** nodes are written using LeafWriter, and read using LeafReader (to -** iterate through a single leaf node's data) and LeavesReader (to -** iterate through a segment's entire leaf layer). Leaf nodes have -** the format: -** -** varint iHeight; (height from leaf level, always 0) -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of prefix shared with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix];(unshared suffix of next term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. -** -** Leaf nodes are broken into blocks which are stored contiguously in -** the %_segments table in sorted order. This means that when the end -** of a node is reached, the next term is in the node with the next -** greater node id. -** -** New data is spilled to a new leaf node when the current node -** exceeds LEAF_MAX bytes (default 2048). New data which itself is -** larger than STANDALONE_MIN (default 1024) is placed in a standalone -** node (a leaf node with a single term and doclist). The goal of -** these settings is to pack together groups of small doclists while -** making it efficient to directly access large doclists. The -** assumption is that large doclists represent terms which are more -** likely to be query targets. -** -** TODO(shess) It may be useful for blocking decisions to be more -** dynamic. For instance, it may make more sense to have a 2.5k leaf -** node rather than splitting into 2k and .5k nodes. My intuition is -** that this might extend through 2x or 4x the pagesize. -** -** -**** Segment interior nodes **** -** Segment interior nodes store blockids for subtree nodes and terms -** to describe what data is stored by the each subtree. Interior -** nodes are written using InteriorWriter, and read using -** InteriorReader. InteriorWriters are created as needed when -** SegmentWriter creates new leaf nodes, or when an interior node -** itself grows too big and must be split. The format of interior -** nodes: -** -** varint iHeight; (height from leaf level, always >0) -** varint iBlockid; (block id of node's leftmost subtree) -** optional { -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of shared prefix with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix]; (unshared suffix of next term) -** } -** } -** -** Here, optional { X } means an optional element, while array { X } -** means zero or more occurrences of X, adjacent in memory. -** -** An interior node encodes n terms separating n+1 subtrees. The -** subtree blocks are contiguous, so only the first subtree's blockid -** is encoded. The subtree at iBlockid will contain all terms less -** than the first term encoded (or all terms if no term is encoded). -** Otherwise, for terms greater than or equal to pTerm[i] but less -** than pTerm[i+1], the subtree for that term will be rooted at -** iBlockid+i. Interior nodes only store enough term data to -** distinguish adjacent children (if the rightmost term of the left -** child is "something", and the leftmost term of the right child is -** "wicked", only "w" is stored). -** -** New data is spilled to a new interior node at the same height when -** the current node exceeds INTERIOR_MAX bytes (default 2048). -** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing -** interior nodes and making the tree too skinny. The interior nodes -** at a given height are naturally tracked by interior nodes at -** height+1, and so on. -** -** -**** Segment directory **** -** The segment directory in table %_segdir stores meta-information for -** merging and deleting segments, and also the root node of the -** segment's tree. -** -** The root node is the top node of the segment's tree after encoding -** the entire segment, restricted to ROOT_MAX bytes (default 1024). -** This could be either a leaf node or an interior node. If the top -** node requires more than ROOT_MAX bytes, it is flushed to %_segments -** and a new root interior node is generated (which should always fit -** within ROOT_MAX because it only needs space for 2 varints, the -** height and the blockid of the previous root). -** -** The meta-information in the segment directory is: -** level - segment level (see below) -** idx - index within level -** - (level,idx uniquely identify a segment) -** start_block - first leaf node -** leaves_end_block - last leaf node -** end_block - last block (including interior nodes) -** root - contents of root node -** -** If the root node is a leaf node, then start_block, -** leaves_end_block, and end_block are all 0. -** -** -**** Segment merging **** -** To amortize update costs, segments are grouped into levels and -** merged in batches. Each increase in level represents exponentially -** more documents. -** -** New documents (actually, document updates) are tokenized and -** written individually (using LeafWriter) to a level 0 segment, with -** incrementing idx. When idx reaches MERGE_COUNT (default 16), all -** level 0 segments are merged into a single level 1 segment. Level 1 -** is populated like level 0, and eventually MERGE_COUNT level 1 -** segments are merged to a single level 2 segment (representing -** MERGE_COUNT^2 updates), and so on. -** -** A segment merge traverses all segments at a given level in -** parallel, performing a straightforward sorted merge. Since segment -** leaf nodes are written in to the %_segments table in order, this -** merge traverses the underlying sqlite disk structures efficiently. -** After the merge, all segment blocks from the merged level are -** deleted. -** -** MERGE_COUNT controls how often we merge segments. 16 seems to be -** somewhat of a sweet spot for insertion performance. 32 and 64 show -** very similar performance numbers to 16 on insertion, though they're -** a tiny bit slower (perhaps due to more overhead in merge-time -** sorting). 8 is about 20% slower than 16, 4 about 50% slower than -** 16, 2 about 66% slower than 16. -** -** At query time, high MERGE_COUNT increases the number of segments -** which need to be scanned and merged. For instance, with 100k docs -** inserted: -** -** MERGE_COUNT segments -** 16 25 -** 8 12 -** 4 10 -** 2 6 -** -** This appears to have only a moderate impact on queries for very -** frequent terms (which are somewhat dominated by segment merge -** costs), and infrequent and non-existent terms still seem to be fast -** even with many segments. -** -** TODO(shess) That said, it would be nice to have a better query-side -** argument for MERGE_COUNT of 16. Also, it is possible/likely that -** optimizations to things like doclist merging will swing the sweet -** spot around. -** -** -** -**** Handling of deletions and updates **** -** Since we're using a segmented structure, with no docid-oriented -** index into the term index, we clearly cannot simply update the term -** index when a document is deleted or updated. For deletions, we -** write an empty doclist (varint(docid) varint(POS_END)), for updates -** we simply write the new doclist. Segment merges overwrite older -** data for a particular docid with newer data, so deletes or updates -** will eventually overtake the earlier data and knock it out. The -** query logic likewise merges doclists so that newer data knocks out -** older data. -*/ - -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) -# define SQLITE_CORE 1 -#endif - -#include -#include -#include -#include -#include -#include - -#include "fts3.h" -#ifndef SQLITE_CORE -# include "sqlite3ext.h" - SQLITE_EXTENSION_INIT1 -#endif - -static int fts3EvalNext(Fts3Cursor *pCsr); -static int fts3EvalStart(Fts3Cursor *pCsr); -static int fts3TermSegReaderCursor( - Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); - -#ifndef SQLITE_AMALGAMATION -# if defined(SQLITE_DEBUG) -int sqlite3Fts3Always(int b) { assert( b ); return b; } -int sqlite3Fts3Never(int b) { assert( !b ); return b; } -# endif -#endif - -/* -** This variable is set to false when running tests for which the on disk -** structures should not be corrupt. Otherwise, true. If it is false, extra -** assert() conditions in the fts3 code are activated - conditions that are -** only true if it is guaranteed that the fts3 database is not corrupt. -*/ -int sqlite3_fts3_may_be_corrupt = 1; - -/* -** Write a 64-bit variable-length integer to memory starting at p[0]. -** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. -** The number of bytes written is returned. -*/ -int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ - unsigned char *q = (unsigned char *) p; - sqlite_uint64 vu = v; - do{ - *q++ = (unsigned char) ((vu & 0x7f) | 0x80); - vu >>= 7; - }while( vu!=0 ); - q[-1] &= 0x7f; /* turn off high bit in final byte */ - assert( q - (unsigned char *)p <= FTS3_VARINT_MAX ); - return (int) (q - (unsigned char *)p); -} - -#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \ - v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \ - if( (v & mask2)==0 ){ var = v; return ret; } -#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \ - v = (*ptr++); \ - if( (v & mask2)==0 ){ var = v; return ret; } - -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ - const unsigned char *p = (const unsigned char*)pBuf; - const unsigned char *pStart = p; - u32 a; - u64 b; - int shift; - - GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1); - GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2); - GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3); - GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4); - b = (a & 0x0FFFFFFF ); - - for(shift=28; shift<=63; shift+=7){ - u64 c = *p++; - b += (c&0x7F) << shift; - if( (c & 0x80)==0 ) break; - } - *v = b; - return (int)(p - pStart); -} - -/* -** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to -** a non-negative 32-bit integer before it is returned. -*/ -int sqlite3Fts3GetVarint32(const char *p, int *pi){ - const unsigned char *ptr = (const unsigned char*)p; - u32 a; - -#ifndef fts3GetVarint32 - GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1); -#else - a = (*ptr++); - assert( a & 0x80 ); -#endif - - GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2); - GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3); - GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4); - a = (a & 0x0FFFFFFF ); - *pi = (int)(a | ((u32)(*ptr & 0x07) << 28)); - assert( 0==(a & 0x80000000) ); - assert( *pi>=0 ); - return 5; -} - -/* -** Return the number of bytes required to encode v as a varint -*/ -int sqlite3Fts3VarintLen(sqlite3_uint64 v){ - int i = 0; - do{ - i++; - v >>= 7; - }while( v!=0 ); - return i; -} - -/* -** Convert an SQL-style quoted string into a normal string by removing -** the quote characters. The conversion is done in-place. If the -** input does not begin with a quote character, then this routine -** is a no-op. -** -** Examples: -** -** "abc" becomes abc -** 'xyz' becomes xyz -** [pqr] becomes pqr -** `mno` becomes mno -** -*/ -void sqlite3Fts3Dequote(char *z){ - char quote; /* Quote character (if any ) */ - - quote = z[0]; - if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ - int iIn = 1; /* Index of next byte to read from input */ - int iOut = 0; /* Index of next byte to write to output */ - - /* If the first byte was a '[', then the close-quote character is a ']' */ - if( quote=='[' ) quote = ']'; - - while( z[iIn] ){ - if( z[iIn]==quote ){ - if( z[iIn+1]!=quote ) break; - z[iOut++] = quote; - iIn += 2; - }else{ - z[iOut++] = z[iIn++]; - } - } - z[iOut] = '\0'; - } -} - -/* -** Read a single varint from the doclist at *pp and advance *pp to point -** to the first byte past the end of the varint. Add the value of the varint -** to *pVal. -*/ -static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); - *pVal += iVal; -} - -/* -** When this function is called, *pp points to the first byte following a -** varint that is part of a doclist (or position-list, or any other list -** of varints). This function moves *pp to point to the start of that varint, -** and sets *pVal by the varint value. -** -** Argument pStart points to the first byte of the doclist that the -** varint is part of. -*/ -static void fts3GetReverseVarint( - char **pp, - char *pStart, - sqlite3_int64 *pVal -){ - sqlite3_int64 iVal; - char *p; - - /* Pointer p now points at the first byte past the varint we are - ** interested in. So, unless the doclist is corrupt, the 0x80 bit is - ** clear on character p[-1]. */ - for(p = (*pp)-2; p>=pStart && *p&0x80; p--); - p++; - *pp = p; - - sqlite3Fts3GetVarint(p, &iVal); - *pVal = iVal; -} - -/* -** The xDisconnect() virtual table method. -*/ -static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int i; - - assert( p->nPendingData==0 ); - assert( p->pSegments==0 ); - - /* Free any prepared statements held */ - sqlite3_finalize(p->pSeekStmt); - for(i=0; iaStmt); i++){ - sqlite3_finalize(p->aStmt[i]); - } - sqlite3_free(p->zSegmentsTbl); - sqlite3_free(p->zReadExprlist); - sqlite3_free(p->zWriteExprlist); - sqlite3_free(p->zContentTbl); - sqlite3_free(p->zLanguageid); - - /* Invoke the tokenizer destructor to free the tokenizer. */ - p->pTokenizer->pModule->xDestroy(p->pTokenizer); - - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Write an error message into *pzErr -*/ -void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ - va_list ap; - sqlite3_free(*pzErr); - va_start(ap, zFormat); - *pzErr = sqlite3_vmprintf(zFormat, ap); - va_end(ap); -} - -/* -** Construct one or more SQL statements from the format string given -** and then evaluate those statements. The success code is written -** into *pRc. -** -** If *pRc is initially non-zero then this routine is a no-op. -*/ -static void fts3DbExec( - int *pRc, /* Success code */ - sqlite3 *db, /* Database in which to run SQL */ - const char *zFormat, /* Format string for SQL */ - ... /* Arguments to the format string */ -){ - va_list ap; - char *zSql; - if( *pRc ) return; - va_start(ap, zFormat); - zSql = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( zSql==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - *pRc = sqlite3_exec(db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } -} - -/* -** The xDestroy() virtual table method. -*/ -static int fts3DestroyMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return code */ - const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */ - sqlite3 *db = p->db; /* Database handle */ - - /* Drop the shadow tables */ - fts3DbExec(&rc, db, - "DROP TABLE IF EXISTS %Q.'%q_segments';" - "DROP TABLE IF EXISTS %Q.'%q_segdir';" - "DROP TABLE IF EXISTS %Q.'%q_docsize';" - "DROP TABLE IF EXISTS %Q.'%q_stat';" - "%s DROP TABLE IF EXISTS %Q.'%q_content';", - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - zDb, p->zName, - (p->zContentTbl ? "--" : ""), zDb,p->zName - ); - - /* If everything has worked, invoke fts3DisconnectMethod() to free the - ** memory associated with the Fts3Table structure and return SQLITE_OK. - ** Otherwise, return an SQLite error code. - */ - return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc); -} - - -/* -** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table -** passed as the first argument. This is done as part of the xConnect() -** and xCreate() methods. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DeclareVtab(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int i; /* Iterator variable */ - int rc; /* Return code */ - char *zSql; /* SQL statement passed to declare_vtab() */ - char *zCols; /* List of user defined columns */ - const char *zLanguageid; - - zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); - sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - - /* Create a list of user columns for the virtual table */ - zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); - for(i=1; zCols && inColumn; i++){ - zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); - } - - /* Create the whole "CREATE TABLE" statement to pass to SQLite */ - zSql = sqlite3_mprintf( - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", - zCols, p->zName, zLanguageid - ); - if( !zCols || !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_declare_vtab(p->db, zSql); - } - - sqlite3_free(zSql); - sqlite3_free(zCols); - *pRc = rc; - } -} - -/* -** Create the %_stat table if it does not already exist. -*/ -void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){ - fts3DbExec(pRc, p->db, - "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'" - "(id INTEGER PRIMARY KEY, value BLOB);", - p->zDb, p->zName - ); - if( (*pRc)==SQLITE_OK ) p->bHasStat = 1; -} - -/* -** Create the backing store tables (%_content, %_segments and %_segdir) -** required by the FTS3 table passed as the only argument. This is done -** as part of the vtab xCreate() method. -** -** If the p->bHasDocsize boolean is true (indicating that this is an -** FTS4 table, not an FTS3 table) then also create the %_docsize and -** %_stat tables required by FTS4. -*/ -static int fts3CreateTables(Fts3Table *p){ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - sqlite3 *db = p->db; /* The database connection */ - - if( p->zContentTbl==0 ){ - const char *zLanguageid = p->zLanguageid; - char *zContentCols; /* Columns of %_content table */ - - /* Create a list of user columns for the content table */ - zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); - for(i=0; zContentCols && inColumn; i++){ - char *z = p->azColumn[i]; - zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); - } - if( zLanguageid && zContentCols ){ - zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); - } - if( zContentCols==0 ) rc = SQLITE_NOMEM; - - /* Create the content table */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_content'(%s)", - p->zDb, p->zName, zContentCols - ); - sqlite3_free(zContentCols); - } - - /* Create other tables */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", - p->zDb, p->zName - ); - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segdir'(" - "level INTEGER," - "idx INTEGER," - "start_block INTEGER," - "leaves_end_block INTEGER," - "end_block INTEGER," - "root BLOB," - "PRIMARY KEY(level, idx)" - ");", - p->zDb, p->zName - ); - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", - p->zDb, p->zName - ); - } - assert( p->bHasStat==p->bFts4 ); - if( p->bHasStat ){ - sqlite3Fts3CreateStatTable(&rc, p); - } - return rc; -} - -/* -** Store the current database page-size in bytes in p->nPgsz. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int rc; /* Return code */ - char *zSql; /* SQL text "PRAGMA %Q.page_size" */ - sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */ - - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_step(pStmt); - p->nPgsz = sqlite3_column_int(pStmt, 0); - rc = sqlite3_finalize(pStmt); - }else if( rc==SQLITE_AUTH ){ - p->nPgsz = 1024; - rc = SQLITE_OK; - } - } - assert( p->nPgsz>0 || rc!=SQLITE_OK ); - sqlite3_free(zSql); - *pRc = rc; - } -} - -/* -** "Special" FTS4 arguments are column specifications of the following form: -** -** = -** -** There may not be whitespace surrounding the "=" character. The -** term may be quoted, but the may not. -*/ -static int fts3IsSpecialColumn( - const char *z, - int *pnKey, - char **pzValue -){ - char *zValue; - const char *zCsr = z; - - while( *zCsr!='=' ){ - if( *zCsr=='\0' ) return 0; - zCsr++; - } - - *pnKey = (int)(zCsr-z); - zValue = sqlite3_mprintf("%s", &zCsr[1]); - if( zValue ){ - sqlite3Fts3Dequote(zValue); - } - *pzValue = zValue; - return 1; -} - -/* -** Append the output of a printf() style formatting to an existing string. -*/ -static void fts3Appendf( - int *pRc, /* IN/OUT: Error code */ - char **pz, /* IN/OUT: Pointer to string buffer */ - const char *zFormat, /* Printf format string to append */ - ... /* Arguments for printf format string */ -){ - if( *pRc==SQLITE_OK ){ - va_list ap; - char *z; - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( z && *pz ){ - char *z2 = sqlite3_mprintf("%s%s", *pz, z); - sqlite3_free(z); - z = z2; - } - if( z==0 ) *pRc = SQLITE_NOMEM; - sqlite3_free(*pz); - *pz = z; - } -} - -/* -** Return a copy of input string zInput enclosed in double-quotes (") and -** with all double quote characters escaped. For example: -** -** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\"" -** -** The pointer returned points to memory obtained from sqlite3_malloc(). It -** is the callers responsibility to call sqlite3_free() to release this -** memory. -*/ -static char *fts3QuoteId(char const *zInput){ - sqlite3_int64 nRet; - char *zRet; - nRet = 2 + (int)strlen(zInput)*2 + 1; - zRet = sqlite3_malloc64(nRet); - if( zRet ){ - int i; - char *z = zRet; - *(z++) = '"'; - for(i=0; zInput[i]; i++){ - if( zInput[i]=='"' ) *(z++) = '"'; - *(z++) = zInput[i]; - } - *(z++) = '"'; - *(z++) = '\0'; - } - return zRet; -} - -/* -** Return a list of comma separated SQL expressions and a FROM clause that -** could be used in a SELECT statement such as the following: -** -** SELECT FROM %_content AS x ... -** -** to return the docid, followed by each column of text data in order -** from left to write. If parameter zFunc is not NULL, then instead of -** being returned directly each column of text data is passed to an SQL -** function named zFunc first. For example, if zFunc is "unzip" and the -** table has the three user-defined columns "a", "b", and "c", the following -** string is returned: -** -** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( p->zContentTbl==0 ){ - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "docid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); - } - sqlite3_free(zFree); - }else{ - fts3Appendf(pRc, &zRet, "rowid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); - } - } - fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", - p->zDb, - (p->zContentTbl ? p->zContentTbl : p->zName), - (p->zContentTbl ? "" : "_content") - ); - return zRet; -} - -/* -** Return a list of N comma separated question marks, where N is the number -** of columns in the %_content table (one for the docid plus one for each -** user-defined text column). -** -** If argument zFunc is not NULL, then all but the first question mark -** is preceded by zFunc and an open bracket, and followed by a closed -** bracket. For example, if zFunc is "zip" and the FTS3 table has three -** user-defined text columns, the following string is returned: -** -** "?, zip(?), zip(?), zip(?)" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "?"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", ?"); - } - sqlite3_free(zFree); - return zRet; -} - -/* -** This function interprets the string at (*pp) as a non-negative integer -** value. It reads the integer and sets *pnOut to the value read, then -** sets *pp to point to the byte immediately following the last byte of -** the integer value. -** -** Only decimal digits ('0'..'9') may be part of an integer value. -** -** If *pp does not being with a decimal digit SQLITE_ERROR is returned and -** the output value undefined. Otherwise SQLITE_OK is returned. -** -** This function is used when parsing the "prefix=" FTS4 parameter. -*/ -static int fts3GobbleInt(const char **pp, int *pnOut){ - const int MAX_NPREFIX = 10000000; - const char *p; /* Iterator pointer */ - int nInt = 0; /* Output value */ - - for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ - nInt = nInt * 10 + (p[0] - '0'); - if( nInt>MAX_NPREFIX ){ - nInt = 0; - break; - } - } - if( p==*pp ) return SQLITE_ERROR; - *pnOut = nInt; - *pp = p; - return SQLITE_OK; -} - -/* -** This function is called to allocate an array of Fts3Index structures -** representing the indexes maintained by the current FTS table. FTS tables -** always maintain the main "terms" index, but may also maintain one or -** more "prefix" indexes, depending on the value of the "prefix=" parameter -** (if any) specified as part of the CREATE VIRTUAL TABLE statement. -** -** Argument zParam is passed the value of the "prefix=" option if one was -** specified, or NULL otherwise. -** -** If no error occurs, SQLITE_OK is returned and *apIndex set to point to -** the allocated array. *pnIndex is set to the number of elements in the -** array. If an error does occur, an SQLite error code is returned. -** -** Regardless of whether or not an error is returned, it is the responsibility -** of the caller to call sqlite3_free() on the output array to free it. -*/ -static int fts3PrefixParameter( - const char *zParam, /* ABC in prefix=ABC parameter to parse */ - int *pnIndex, /* OUT: size of *apIndex[] array */ - struct Fts3Index **apIndex /* OUT: Array of indexes for this table */ -){ - struct Fts3Index *aIndex; /* Allocated array */ - int nIndex = 1; /* Number of entries in array */ - - if( zParam && zParam[0] ){ - const char *p; - nIndex++; - for(p=zParam; *p; p++){ - if( *p==',' ) nIndex++; - } - } - - aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex); - *apIndex = aIndex; - if( !aIndex ){ - return SQLITE_NOMEM; - } - - memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); - if( zParam ){ - const char *p = zParam; - int i; - for(i=1; i=0 ); - if( nPrefix==0 ){ - nIndex--; - i--; - }else{ - aIndex[i].nPrefix = nPrefix; - } - p++; - } - } - - *pnIndex = nIndex; - return SQLITE_OK; -} - -/* -** This function is called when initializing an FTS4 table that uses the -** content=xxx option. It determines the number of and names of the columns -** of the new FTS4 table. -** -** The third argument passed to this function is the value passed to the -** config=xxx option (i.e. "xxx"). This function queries the database for -** a table of that name. If found, the output variables are populated -** as follows: -** -** *pnCol: Set to the number of columns table xxx has, -** -** *pnStr: Set to the total amount of space required to store a copy -** of each columns name, including the nul-terminator. -** -** *pazCol: Set to point to an array of *pnCol strings. Each string is -** the name of the corresponding column in table xxx. The array -** and its contents are allocated using a single allocation. It -** is the responsibility of the caller to free this allocation -** by eventually passing the *pazCol value to sqlite3_free(). -** -** If the table cannot be found, an error code is returned and the output -** variables are undefined. Or, if an OOM is encountered, SQLITE_NOMEM is -** returned (and the output variables are undefined). -*/ -static int fts3ContentColumns( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ - const char *zTbl, /* Name of content table */ - const char ***pazCol, /* OUT: Malloc'd array of column names */ - int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr, /* OUT: Bytes of string content */ - char **pzErr /* OUT: error message */ -){ - int rc = SQLITE_OK; /* Return code */ - char *zSql; /* "SELECT *" statement on zTbl */ - sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ - - zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); - } - } - sqlite3_free(zSql); - - if( rc==SQLITE_OK ){ - const char **azCol; /* Output array */ - sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */ - int nCol; /* Number of table columns */ - int i; /* Used to iterate through columns */ - - /* Loop through the returned columns. Set nStr to the number of bytes of - ** space required to store a copy of each column name, including the - ** nul-terminator byte. */ - nCol = sqlite3_column_count(pStmt); - for(i=0; i module name ("fts3" or "fts4") -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> "column name" and other module argument fields. -*/ -static int fts3InitVtab( - int isCreate, /* True for xCreate, false for xConnect */ - sqlite3 *db, /* The SQLite database connection */ - void *pAux, /* Hash table containing tokenizers */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ - char **pzErr /* Write any error message here */ -){ - Fts3Hash *pHash = (Fts3Hash *)pAux; - Fts3Table *p = 0; /* Pointer to allocated vtab */ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - sqlite3_int64 nByte; /* Size of allocation used for *p */ - int iCol; /* Column index */ - int nString = 0; /* Bytes required to hold all column names */ - int nCol = 0; /* Number of columns in the FTS table */ - char *zCsr; /* Space for holding column names */ - int nDb; /* Bytes required to hold database name */ - int nName; /* Bytes required to hold table name */ - int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ - const char **aCol; /* Array of column names */ - sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - - int nIndex = 0; /* Size of aIndex[] array */ - struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ - - /* The results of parsing supported FTS4 key=value options: */ - int bNoDocsize = 0; /* True to omit %_docsize table */ - int bDescIdx = 0; /* True to store descending indexes */ - char *zPrefix = 0; /* Prefix parameter value (or NULL) */ - char *zCompress = 0; /* compress=? parameter (or NULL) */ - char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ - char *zContent = 0; /* content=? parameter (or NULL) */ - char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ - char **azNotindexed = 0; /* The set of notindexed= columns */ - int nNotindexed = 0; /* Size of azNotindexed[] array */ - - assert( strlen(argv[0])==4 ); - assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) - || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) - ); - - nDb = (int)strlen(argv[1]) + 1; - nName = (int)strlen(argv[2]) + 1; - - nByte = sizeof(const char *) * (argc-2); - aCol = (const char **)sqlite3_malloc64(nByte); - if( aCol ){ - memset((void*)aCol, 0, nByte); - azNotindexed = (char **)sqlite3_malloc64(nByte); - } - if( azNotindexed ){ - memset(azNotindexed, 0, nByte); - } - if( !aCol || !azNotindexed ){ - rc = SQLITE_NOMEM; - goto fts3_init_out; - } - - /* Loop through all of the arguments passed by the user to the FTS3/4 - ** module (i.e. all the column names and special arguments). This loop - ** does the following: - ** - ** + Figures out the number of columns the FTSX table will have, and - ** the number of bytes of space that must be allocated to store copies - ** of the column names. - ** - ** + If there is a tokenizer specification included in the arguments, - ** initializes the tokenizer pTokenizer. - */ - for(i=3; rc==SQLITE_OK && i8 - && 0==sqlite3_strnicmp(z, "tokenize", 8) - && 0==sqlite3Fts3IsIdChar(z[8]) - ){ - rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr); - } - - /* Check if it is an FTS4 special argument. */ - else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){ - struct Fts4Option { - const char *zOpt; - int nOpt; - } aFts4Opt[] = { - { "matchinfo", 9 }, /* 0 -> MATCHINFO */ - { "prefix", 6 }, /* 1 -> PREFIX */ - { "compress", 8 }, /* 2 -> COMPRESS */ - { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ - { "order", 5 }, /* 4 -> ORDER */ - { "content", 7 }, /* 5 -> CONTENT */ - { "languageid", 10 }, /* 6 -> LANGUAGEID */ - { "notindexed", 10 } /* 7 -> NOTINDEXED */ - }; - - int iOpt; - if( !zVal ){ - rc = SQLITE_NOMEM; - }else{ - for(iOpt=0; iOptnOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ - break; - } - } - switch( iOpt ){ - case 0: /* MATCHINFO */ - if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); - rc = SQLITE_ERROR; - } - bNoDocsize = 1; - break; - - case 1: /* PREFIX */ - sqlite3_free(zPrefix); - zPrefix = zVal; - zVal = 0; - break; - - case 2: /* COMPRESS */ - sqlite3_free(zCompress); - zCompress = zVal; - zVal = 0; - break; - - case 3: /* UNCOMPRESS */ - sqlite3_free(zUncompress); - zUncompress = zVal; - zVal = 0; - break; - - case 4: /* ORDER */ - if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) - && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) - ){ - sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); - rc = SQLITE_ERROR; - } - bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); - break; - - case 5: /* CONTENT */ - sqlite3_free(zContent); - zContent = zVal; - zVal = 0; - break; - - case 6: /* LANGUAGEID */ - assert( iOpt==6 ); - sqlite3_free(zLanguageid); - zLanguageid = zVal; - zVal = 0; - break; - - case 7: /* NOTINDEXED */ - azNotindexed[nNotindexed++] = zVal; - zVal = 0; - break; - - default: - assert( iOpt==SizeofArray(aFts4Opt) ); - sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); - rc = SQLITE_ERROR; - break; - } - sqlite3_free(zVal); - } - } - - /* Otherwise, the argument is a column name. */ - else { - nString += (int)(strlen(z) + 1); - aCol[nCol++] = z; - } - } - - /* If a content=xxx option was specified, the following: - ** - ** 1. Ignore any compress= and uncompress= options. - ** - ** 2. If no column names were specified as part of the CREATE VIRTUAL - ** TABLE statement, use all columns from the content table. - */ - if( rc==SQLITE_OK && zContent ){ - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - zCompress = 0; - zUncompress = 0; - if( nCol==0 ){ - sqlite3_free((void*)aCol); - aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); - - /* If a languageid= option was specified, remove the language id - ** column from the aCol[] array. */ - if( rc==SQLITE_OK && zLanguageid ){ - int j; - for(j=0; jdb = db; - p->nColumn = nCol; - p->nPendingData = 0; - p->azColumn = (char **)&p[1]; - p->pTokenizer = pTokenizer; - p->nMaxPendingData = FTS3_MAX_PENDING_DATA; - p->bHasDocsize = (isFts4 && bNoDocsize==0); - p->bHasStat = (u8)isFts4; - p->bFts4 = (u8)isFts4; - p->bDescIdx = (u8)bDescIdx; - p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ - p->zContentTbl = zContent; - p->zLanguageid = zLanguageid; - zContent = 0; - zLanguageid = 0; - TESTONLY( p->inTransaction = -1 ); - TESTONLY( p->mxSavepoint = -1 ); - - p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; - memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); - p->nIndex = nIndex; - for(i=0; iaIndex[i].hPending, FTS3_HASH_STRING, 1); - } - p->abNotindexed = (u8 *)&p->aIndex[nIndex]; - - /* Fill in the zName and zDb fields of the vtab structure. */ - zCsr = (char *)&p->abNotindexed[nCol]; - p->zName = zCsr; - memcpy(zCsr, argv[2], nName); - zCsr += nName; - p->zDb = zCsr; - memcpy(zCsr, argv[1], nDb); - zCsr += nDb; - - /* Fill in the azColumn array */ - for(iCol=0; iCol0 ){ - memcpy(zCsr, z, n); - } - zCsr[n] = '\0'; - sqlite3Fts3Dequote(zCsr); - p->azColumn[iCol] = zCsr; - zCsr += n+1; - assert( zCsr <= &((char *)p)[nByte] ); - } - - /* Fill in the abNotindexed array */ - for(iCol=0; iColazColumn[iCol]); - for(i=0; iazColumn[iCol], zNot, n) - ){ - p->abNotindexed[iCol] = 1; - sqlite3_free(zNot); - azNotindexed[i] = 0; - } - } - } - for(i=0; izReadExprlist = fts3ReadExprList(p, zUncompress, &rc); - p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); - if( rc!=SQLITE_OK ) goto fts3_init_out; - - /* If this is an xCreate call, create the underlying tables in the - ** database. TODO: For xConnect(), it could verify that said tables exist. - */ - if( isCreate ){ - rc = fts3CreateTables(p); - } - - /* Check to see if a legacy fts3 table has been "upgraded" by the - ** addition of a %_stat table so that it can use incremental merge. - */ - if( !isFts4 && !isCreate ){ - p->bHasStat = 2; - } - - /* Figure out the page-size for the database. This is required in order to - ** estimate the cost of loading large doclists from the database. */ - fts3DatabasePageSize(&rc, p); - p->nNodeSize = p->nPgsz-35; - - /* Declare the table schema to SQLite. */ - fts3DeclareVtab(&rc, p); - -fts3_init_out: - sqlite3_free(zPrefix); - sqlite3_free(aIndex); - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - sqlite3_free(zContent); - sqlite3_free(zLanguageid); - for(i=0; ipModule->xDestroy(pTokenizer); - } - }else{ - assert( p->pSegments==0 ); - *ppVTab = &p->base; - } - return rc; -} - -/* -** The xConnect() and xCreate() methods for the virtual table. All the -** work is done in function fts3InitVtab(). -*/ -static int fts3ConnectMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr); -} -static int fts3CreateMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr); -} - -/* -** Set the pIdxInfo->estimatedRows variable to nRow. Unless this -** extension is currently being used by a version of SQLite too old to -** support estimatedRows. In that case this function is a no-op. -*/ -static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ -#if SQLITE_VERSION_NUMBER>=3008002 - if( sqlite3_libversion_number()>=3008002 ){ - pIdxInfo->estimatedRows = nRow; - } -#endif -} - -/* -** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this -** extension is currently being used by a version of SQLite too old to -** support index-info flags. In that case this function is a no-op. -*/ -static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ -#if SQLITE_VERSION_NUMBER>=3008012 - if( sqlite3_libversion_number()>=3008012 ){ - pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; - } -#endif -} - -/* -** Implementation of the xBestIndex method for FTS3 tables. There -** are three possible strategies, in order of preference: -** -** 1. Direct lookup by rowid or docid. -** 2. Full-text search using a MATCH operator on a non-docid column. -** 3. Linear scan of %_content table. -*/ -static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ - Fts3Table *p = (Fts3Table *)pVTab; - int i; /* Iterator variable */ - int iCons = -1; /* Index of constraint to use */ - - int iLangidCons = -1; /* Index of langid=x constraint, if present */ - int iDocidGe = -1; /* Index of docid>=x constraint, if present */ - int iDocidLe = -1; /* Index of docid<=x constraint, if present */ - int iIdx; - - /* By default use a full table scan. This is an expensive option, - ** so search through the constraints to see if a more efficient - ** strategy is possible. - */ - pInfo->idxNum = FTS3_FULLSCAN_SEARCH; - pInfo->estimatedCost = 5000000; - for(i=0; inConstraint; i++){ - int bDocid; /* True if this constraint is on docid */ - struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; - if( pCons->usable==0 ){ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ - /* There exists an unusable MATCH constraint. This means that if - ** the planner does elect to use the results of this call as part - ** of the overall query plan the user will see an "unable to use - ** function MATCH in the requested context" error. To discourage - ** this, return a very high cost here. */ - pInfo->idxNum = FTS3_FULLSCAN_SEARCH; - pInfo->estimatedCost = 1e50; - fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50); - return SQLITE_OK; - } - continue; - } - - bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1); - - /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ - if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){ - pInfo->idxNum = FTS3_DOCID_SEARCH; - pInfo->estimatedCost = 1.0; - iCons = i; - } - - /* A MATCH constraint. Use a full-text search. - ** - ** If there is more than one MATCH constraint available, use the first - ** one encountered. If there is both a MATCH constraint and a direct - ** rowid/docid lookup, prefer the MATCH strategy. This is done even - ** though the rowid/docid lookup is faster than a MATCH query, selecting - ** it would lead to an "unable to use function MATCH in the requested - ** context" error. - */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH - && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn - ){ - pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; - pInfo->estimatedCost = 2.0; - iCons = i; - } - - /* Equality constraint on the langid column */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ - && pCons->iColumn==p->nColumn + 2 - ){ - iLangidCons = i; - } - - if( bDocid ){ - switch( pCons->op ){ - case SQLITE_INDEX_CONSTRAINT_GE: - case SQLITE_INDEX_CONSTRAINT_GT: - iDocidGe = i; - break; - - case SQLITE_INDEX_CONSTRAINT_LE: - case SQLITE_INDEX_CONSTRAINT_LT: - iDocidLe = i; - break; - } - } - } - - /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ - if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); - - iIdx = 1; - if( iCons>=0 ){ - pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; - pInfo->aConstraintUsage[iCons].omit = 1; - } - if( iLangidCons>=0 ){ - pInfo->idxNum |= FTS3_HAVE_LANGID; - pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; - } - if( iDocidGe>=0 ){ - pInfo->idxNum |= FTS3_HAVE_DOCID_GE; - pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++; - } - if( iDocidLe>=0 ){ - pInfo->idxNum |= FTS3_HAVE_DOCID_LE; - pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++; - } - - /* Regardless of the strategy selected, FTS can deliver rows in rowid (or - ** docid) order. Both ascending and descending are possible. - */ - if( pInfo->nOrderBy==1 ){ - struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0]; - if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){ - if( pOrder->desc ){ - pInfo->idxStr = "DESC"; - }else{ - pInfo->idxStr = "ASC"; - } - pInfo->orderByConsumed = 1; - } - } - - assert( p->pSegments==0 ); - return SQLITE_OK; -} - -/* -** Implementation of xOpen method. -*/ -static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ - - UNUSED_PARAMETER(pVTab); - - /* Allocate a buffer large enough for an Fts3Cursor structure. If the - ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, - ** if the allocation fails, return SQLITE_NOMEM. - */ - *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3Cursor)); - return SQLITE_OK; -} - -/* -** Finalize the statement handle at pCsr->pStmt. -** -** Or, if that statement handle is one created by fts3CursorSeekStmt(), -** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement -** pointer there instead of finalizing it. -*/ -static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ - if( pCsr->bSeekStmt ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - if( p->pSeekStmt==0 ){ - p->pSeekStmt = pCsr->pStmt; - sqlite3_reset(pCsr->pStmt); - pCsr->pStmt = 0; - } - pCsr->bSeekStmt = 0; - } - sqlite3_finalize(pCsr->pStmt); -} - -/* -** Free all resources currently held by the cursor passed as the only -** argument. -*/ -static void fts3ClearCursor(Fts3Cursor *pCsr){ - fts3CursorFinalizeStmt(pCsr); - sqlite3Fts3FreeDeferredTokens(pCsr); - sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - sqlite3Fts3ExprFree(pCsr->pExpr); - memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); -} - -/* -** Close the cursor. For additional information see the documentation -** on the xClose method of the virtual table interface. -*/ -static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - fts3ClearCursor(pCsr); - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then -** compose and prepare an SQL statement of the form: -** -** "SELECT FROM %_content WHERE rowid = ?" -** -** (or the equivalent for a content=xxx table) and set pCsr->pStmt to -** it. If an error occurs, return an SQLite error code. -*/ -static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; - if( pCsr->pStmt==0 ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - char *zSql; - if( p->pSeekStmt ){ - pCsr->pStmt = p->pSeekStmt; - p->pSeekStmt = 0; - }else{ - zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); - if( !zSql ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); - sqlite3_free(zSql); - } - if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; - } - return rc; -} - -/* -** Position the pCsr->pStmt statement so that it is on the row -** of the %_content table that contains the last match. Return -** SQLITE_OK on success. -*/ -static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ - int rc = SQLITE_OK; - if( pCsr->isRequireSeek ){ - rc = fts3CursorSeekStmt(pCsr); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); - pCsr->isRequireSeek = 0; - if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ - return SQLITE_OK; - }else{ - rc = sqlite3_reset(pCsr->pStmt); - if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ - /* If no row was found and no error has occurred, then the %_content - ** table is missing a row that is present in the full-text index. - ** The data structures are corrupt. */ - rc = FTS_CORRUPT_VTAB; - pCsr->isEof = 1; - } - } - } - } - - if( rc!=SQLITE_OK && pContext ){ - sqlite3_result_error_code(pContext, rc); - } - return rc; -} - -/* -** This function is used to process a single interior node when searching -** a b-tree for a term or term prefix. The node data is passed to this -** function via the zNode/nNode parameters. The term to search for is -** passed in zTerm/nTerm. -** -** If piFirst is not NULL, then this function sets *piFirst to the blockid -** of the child node that heads the sub-tree that may contain the term. -** -** If piLast is not NULL, then *piLast is set to the right-most child node -** that heads a sub-tree that may contain a term for which zTerm/nTerm is -** a prefix. -** -** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. -*/ -static int fts3ScanInteriorNode( - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piFirst, /* OUT: Selected child node */ - sqlite3_int64 *piLast /* OUT: Selected child node */ -){ - int rc = SQLITE_OK; /* Return code */ - const char *zCsr = zNode; /* Cursor to iterate through node */ - const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ - char *zBuffer = 0; /* Buffer to load terms into */ - i64 nAlloc = 0; /* Size of allocated buffer */ - int isFirstTerm = 1; /* True when processing first term on page */ - sqlite3_int64 iChild; /* Block id of child node to descend to */ - - /* Skip over the 'height' varint that occurs at the start of every - ** interior node. Then load the blockid of the left-child of the b-tree - ** node into variable iChild. - ** - ** Even if the data structure on disk is corrupted, this (reading two - ** varints from the buffer) does not risk an overread. If zNode is a - ** root node, then the buffer comes from a SELECT statement. SQLite does - ** not make this guarantee explicitly, but in practice there are always - ** either more than 20 bytes of allocated space following the nNode bytes of - ** contents, or two zero bytes. Or, if the node is read from the %_segments - ** table, then there are always 20 bytes of zeroed padding following the - ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details). - */ - zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); - zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); - if( zCsr>zEnd ){ - return FTS_CORRUPT_VTAB; - } - - while( zCsr=0 && nSuffix>=0 ); - if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){ - rc = FTS_CORRUPT_VTAB; - goto finish_scan; - } - if( (i64)nPrefix+nSuffix>nAlloc ){ - char *zNew; - nAlloc = ((i64)nPrefix+nSuffix) * 2; - zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); - if( !zNew ){ - rc = SQLITE_NOMEM; - goto finish_scan; - } - zBuffer = zNew; - } - assert( zBuffer ); - memcpy(&zBuffer[nPrefix], zCsr, nSuffix); - nBuffer = nPrefix + nSuffix; - zCsr += nSuffix; - - /* Compare the term we are searching for with the term just loaded from - ** the interior node. If the specified term is greater than or equal - ** to the term from the interior node, then all terms on the sub-tree - ** headed by node iChild are smaller than zTerm. No need to search - ** iChild. - ** - ** If the interior node term is larger than the specified term, then - ** the tree headed by iChild may contain the specified term. - */ - cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer)); - if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){ - *piFirst = iChild; - piFirst = 0; - } - - if( piLast && cmp<0 ){ - *piLast = iChild; - piLast = 0; - } - - iChild++; - }; - - if( piFirst ) *piFirst = iChild; - if( piLast ) *piLast = iChild; - - finish_scan: - sqlite3_free(zBuffer); - return rc; -} - - -/* -** The buffer pointed to by argument zNode (size nNode bytes) contains an -** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes) -** contains a term. This function searches the sub-tree headed by the zNode -** node for the range of leaf nodes that may contain the specified term -** or terms for which the specified term is a prefix. -** -** If piLeaf is not NULL, then *piLeaf is set to the blockid of the -** left-most leaf node in the tree that may contain the specified term. -** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the -** right-most leaf node that may contain a term for which the specified -** term is a prefix. -** -** It is possible that the range of returned leaf nodes does not contain -** the specified term or any terms for which it is a prefix. However, if the -** segment does contain any such terms, they are stored within the identified -** range. Because this function only inspects interior segment nodes (and -** never loads leaf nodes into memory), it is not possible to be sure. -** -** If an error occurs, an error code other than SQLITE_OK is returned. -*/ -static int fts3SelectLeaf( - Fts3Table *p, /* Virtual table handle */ - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piLeaf, /* Selected leaf node */ - sqlite3_int64 *piLeaf2 /* Selected leaf node */ -){ - int rc = SQLITE_OK; /* Return code */ - int iHeight; /* Height of this node in tree */ - - assert( piLeaf || piLeaf2 ); - - fts3GetVarint32(zNode, &iHeight); - rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); - assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); - - if( rc==SQLITE_OK && iHeight>1 ){ - char *zBlob = 0; /* Blob read from %_segments table */ - int nBlob = 0; /* Size of zBlob in bytes */ - - if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ - rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); - if( rc==SQLITE_OK ){ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); - } - sqlite3_free(zBlob); - piLeaf = 0; - zBlob = 0; - } - - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0); - } - if( rc==SQLITE_OK ){ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2); - } - sqlite3_free(zBlob); - } - - return rc; -} - -/* -** This function is used to create delta-encoded serialized lists of FTS3 -** varints. Each call to this function appends a single varint to a list. -*/ -static void fts3PutDeltaVarint( - char **pp, /* IN/OUT: Output pointer */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); - *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); - *piPrev = iVal; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a position-list. After it returns, *ppPoslist points to the -** first byte after the position-list. -** -** A position list is list of positions (delta encoded) and columns for -** a single document record of a doclist. So, in other words, this -** routine advances *ppPoslist so that it points to the next docid in -** the doclist, or to the first byte past the end of the doclist. -** -** If pp is not NULL, then the contents of the position list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. -*/ -static void fts3PoslistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* The end of a position list is marked by a zero encoded as an FTS3 - ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by - ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail - ** of some other, multi-byte, value. - ** - ** The following while-loop moves pEnd to point to the first byte that is not - ** immediately preceded by a byte with the 0x80 bit set. Then increments - ** pEnd once more so that it points to the byte immediately following the - ** last byte in the position-list. - */ - while( *pEnd | c ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && (*pEnd)==0 ); - } - pEnd++; /* Advance past the POS_END terminator byte */ - - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a column-list. After it returns, *ppPoslist points to the -** to the terminator (POS_COLUMN or POS_END) byte of the column-list. -** -** A column-list is list of delta-encoded positions for a single column -** within a single document within a doclist. -** -** The column-list is terminated either by a POS_COLUMN varint (1) or -** a POS_END varint (0). This routine leaves *ppPoslist pointing to -** the POS_COLUMN or POS_END that terminates the column-list. -** -** If pp is not NULL, then the contents of the column-list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. The POS_COLUMN or POS_END terminator -** is not copied into *pp. -*/ -static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* A column-list is terminated by either a 0x01 or 0x00 byte that is - ** not part of a multi-byte varint. - */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && ((*pEnd)&0xfe)==0 ); - } - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** Value used to signify the end of an position-list. This is safe because -** it is not possible to have a document with 2^31 terms. -*/ -#define POSITION_LIST_END 0x7fffffff - -/* -** This function is used to help parse position-lists. When this function is -** called, *pp may point to the start of the next varint in the position-list -** being parsed, or it may point to 1 byte past the end of the position-list -** (in which case **pp will be a terminator bytes POS_END (0) or -** (1)). -** -** If *pp points past the end of the current position-list, set *pi to -** POSITION_LIST_END and return. Otherwise, read the next varint from *pp, -** increment the current value of *pi by the value read, and set *pp to -** point to the next value before returning. -** -** Before calling this routine *pi must be initialized to the value of -** the previous position, or zero if we are reading the first position -** in the position-list. Because positions are delta-encoded, the value -** of the previous position is needed in order to compute the value of -** the next position. -*/ -static void fts3ReadNextPos( - char **pp, /* IN/OUT: Pointer into position-list buffer */ - sqlite3_int64 *pi /* IN/OUT: Value read from position-list */ -){ - if( (**pp)&0xFE ){ - fts3GetDeltaVarint(pp, pi); - *pi -= 2; - }else{ - *pi = POSITION_LIST_END; - } -} - -/* -** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by -** the value of iCol encoded as a varint to *pp. This will start a new -** column list. -** -** Set *pp to point to the byte just after the last byte written before -** returning (do not modify it if iCol==0). Return the total number of bytes -** written (0 if iCol==0). -*/ -static int fts3PutColNumber(char **pp, int iCol){ - int n = 0; /* Number of bytes written */ - if( iCol ){ - char *p = *pp; /* Output pointer */ - n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); - *p = 0x01; - *pp = &p[n]; - } - return n; -} - -/* -** Compute the union of two position lists. The output written -** into *pp contains all positions of both *pp1 and *pp2 in sorted -** order and with any duplicates removed. All pointers are -** updated appropriately. The caller is responsible for insuring -** that there is enough space in *pp to hold the complete output. -*/ -static int fts3PoslistMerge( - char **pp, /* Output buffer */ - char **pp1, /* Left input list */ - char **pp2 /* Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - - while( *p1 || *p2 ){ - int iCol1; /* The current column index in pp1 */ - int iCol2; /* The current column index in pp2 */ - - if( *p1==POS_COLUMN ){ - fts3GetVarint32(&p1[1], &iCol1); - if( iCol1==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p1==POS_END ) iCol1 = POSITION_LIST_END; - else iCol1 = 0; - - if( *p2==POS_COLUMN ){ - fts3GetVarint32(&p2[1], &iCol2); - if( iCol2==0 ) return FTS_CORRUPT_VTAB; - } - else if( *p2==POS_END ) iCol2 = POSITION_LIST_END; - else iCol2 = 0; - - if( iCol1==iCol2 ){ - sqlite3_int64 i1 = 0; /* Last position from pp1 */ - sqlite3_int64 i2 = 0; /* Last position from pp2 */ - sqlite3_int64 iPrev = 0; - int n = fts3PutColNumber(&p, iCol1); - p1 += n; - p2 += n; - - /* At this point, both p1 and p2 point to the start of column-lists - ** for the same column (the column with index iCol1 and iCol2). - ** A column-list is a list of non-negative delta-encoded varints, each - ** incremented by 2 before being stored. Each list is terminated by a - ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists - ** and writes the results to buffer p. p is left pointing to the byte - ** after the list written. No terminator (POS_END or POS_COLUMN) is - ** written to the output. - */ - fts3GetDeltaVarint(&p1, &i1); - fts3GetDeltaVarint(&p2, &i2); - do { - fts3PutDeltaVarint(&p, &iPrev, (i1pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e. -** when the *pp1 token appears before the *pp2 token, but not more than nToken -** slots before it. -** -** e.g. nToken==1 searches for adjacent positions. -*/ -static int fts3PoslistPhraseMerge( - char **pp, /* IN/OUT: Preallocated output buffer */ - int nToken, /* Maximum difference in token positions */ - int isSaveLeft, /* Save the left position */ - int isExact, /* If *pp1 is exactly nTokens before *pp2 */ - char **pp1, /* IN/OUT: Left input list */ - char **pp2 /* IN/OUT: Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - int iCol1 = 0; - int iCol2 = 0; - - /* Never set both isSaveLeft and isExact for the same invocation. */ - assert( isSaveLeft==0 || isExact==0 ); - - assert( p!=0 && *p1!=0 && *p2!=0 ); - if( *p1==POS_COLUMN ){ - p1++; - p1 += fts3GetVarint32(p1, &iCol1); - } - if( *p2==POS_COLUMN ){ - p2++; - p2 += fts3GetVarint32(p2, &iCol2); - } - - while( 1 ){ - if( iCol1==iCol2 ){ - char *pSave = p; - sqlite3_int64 iPrev = 0; - sqlite3_int64 iPos1 = 0; - sqlite3_int64 iPos2 = 0; - - if( iCol1 ){ - *p++ = POS_COLUMN; - p += sqlite3Fts3PutVarint(p, iCol1); - } - - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - if( iPos1<0 || iPos2<0 ) break; - - while( 1 ){ - if( iPos2==iPos1+nToken - || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) - ){ - sqlite3_int64 iSave; - iSave = isSaveLeft ? iPos1 : iPos2; - fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; - pSave = 0; - assert( p ); - } - if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ - if( (*p2&0xFE)==0 ) break; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - }else{ - if( (*p1&0xFE)==0 ) break; - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - } - } - - if( pSave ){ - assert( pp && p ); - p = pSave; - } - - fts3ColumnlistCopy(0, &p1); - fts3ColumnlistCopy(0, &p2); - assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 ); - if( 0==*p1 || 0==*p2 ) break; - - p1++; - p1 += fts3GetVarint32(p1, &iCol1); - p2++; - p2 += fts3GetVarint32(p2, &iCol2); - } - - /* Advance pointer p1 or p2 (whichever corresponds to the smaller of - ** iCol1 and iCol2) so that it points to either the 0x00 that marks the - ** end of the position list, or the 0x01 that precedes the next - ** column-number in the position list. - */ - else if( iCol1=pEnd ){ - *pp = 0; - }else{ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); - if( bDescIdx ){ - *pVal -= iVal; - }else{ - *pVal += iVal; - } - } -} - -/* -** This function is used to write a single varint to a buffer. The varint -** is written to *pp. Before returning, *pp is set to point 1 byte past the -** end of the value written. -** -** If *pbFirst is zero when this function is called, the value written to -** the buffer is that of parameter iVal. -** -** If *pbFirst is non-zero when this function is called, then the value -** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal) -** (if bDescIdx is non-zero). -** -** Before returning, this function always sets *pbFirst to 1 and *piPrev -** to the value of parameter iVal. -*/ -static void fts3PutDeltaVarint3( - char **pp, /* IN/OUT: Output pointer */ - int bDescIdx, /* True for descending docids */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - int *pbFirst, /* IN/OUT: True after first int written */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - sqlite3_int64 iWrite; - if( bDescIdx==0 || *pbFirst==0 ){ - iWrite = iVal - *piPrev; - }else{ - iWrite = *piPrev - iVal; - } - assert( *pbFirst || *piPrev==0 ); - assert( *pbFirst==0 || iWrite>0 ); - *pp += sqlite3Fts3PutVarint(*pp, iWrite); - *piPrev = iVal; - *pbFirst = 1; -} - - -/* -** This macro is used by various functions that merge doclists. The two -** arguments are 64-bit docid values. If the value of the stack variable -** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). -** Otherwise, (i2-i1). -** -** Using this makes it easier to write code that can merge doclists that are -** sorted in either ascending or descending order. -*/ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2)) - -/* -** This function does an "OR" merge of two doclists (output contains all -** positions contained in either argument doclist). If the docids in the -** input doclists are sorted in ascending order, parameter bDescDoclist -** should be false. If they are sorted in ascending order, it should be -** passed a non-zero value. -** -** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer -** containing the output doclist and SQLITE_OK is returned. In this case -** *pnOut is set to the number of bytes in the output doclist. -** -** If an error occurs, an SQLite error code is returned. The output values -** are undefined in this case. -*/ -static int fts3DoclistOrMerge( - int bDescDoclist, /* True if arguments are desc */ - char *a1, int n1, /* First doclist */ - char *a2, int n2, /* Second doclist */ - char **paOut, int *pnOut /* OUT: Malloc'd doclist */ -){ - int rc = SQLITE_OK; - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *pEnd1 = &a1[n1]; - char *pEnd2 = &a2[n2]; - char *p1 = a1; - char *p2 = a2; - char *p; - char *aOut; - int bFirstOut = 0; - - *paOut = 0; - *pnOut = 0; - - /* Allocate space for the output. Both the input and output doclists - ** are delta encoded. If they are in ascending order (bDescDoclist==0), - ** then the first docid in each list is simply encoded as a varint. For - ** each subsequent docid, the varint stored is the difference between the - ** current and previous docid (a positive number - since the list is in - ** ascending order). - ** - ** The first docid written to the output is therefore encoded using the - ** same number of bytes as it is in whichever of the input lists it is - ** read from. And each subsequent docid read from the same input list - ** consumes either the same or less bytes as it did in the input (since - ** the difference between it and the previous value in the output must - ** be a positive value less than or equal to the delta value read from - ** the input list). The same argument applies to all but the first docid - ** read from the 'other' list. And to the contents of all position lists - ** that will be copied and merged from the input to the output. - ** - ** However, if the first docid copied to the output is a negative number, - ** then the encoding of the first docid from the 'other' input list may - ** be larger in the output than it was in the input (since the delta value - ** may be a larger positive integer than the actual docid). - ** - ** The space required to store the output is therefore the sum of the - ** sizes of the two inputs, plus enough space for exactly one of the input - ** docids to grow. - ** - ** A symetric argument may be made if the doclists are in descending - ** order. - */ - aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING); - if( !aOut ) return SQLITE_NOMEM; - - p = aOut; - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - while( p1 || p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - - if( p2 && p1 && iDiff==0 ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - rc = fts3PoslistMerge(&p, &p1, &p2); - if( rc ) break; - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( !p2 || (p1 && iDiff<0) ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - fts3PoslistCopy(&p, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2); - fts3PoslistCopy(&p, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - p = aOut = 0; - }else{ - assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 ); - memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING); - } - *paOut = aOut; - *pnOut = (int)(p-aOut); - return rc; -} - -/* -** This function does a "phrase" merge of two doclists. In a phrase merge, -** the output contains a copy of each position from the right-hand input -** doclist for which there is a position in the left-hand input doclist -** exactly nDist tokens before it. -** -** If the docids in the input doclists are sorted in ascending order, -** parameter bDescDoclist should be false. If they are sorted in ascending -** order, it should be passed a non-zero value. -** -** The right-hand input doclist is overwritten by this function. -*/ -static int fts3DoclistPhraseMerge( - int bDescDoclist, /* True if arguments are desc */ - int nDist, /* Distance from left to right (1=adjacent) */ - char *aLeft, int nLeft, /* Left doclist */ - char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ -){ - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *aRight = *paRight; - char *pEnd1 = &aLeft[nLeft]; - char *pEnd2 = &aRight[*pnRight]; - char *p1 = aLeft; - char *p2 = aRight; - char *p; - int bFirstOut = 0; - char *aOut; - - assert( nDist>0 ); - if( bDescDoclist ){ - aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX); - if( aOut==0 ) return SQLITE_NOMEM; - }else{ - aOut = aRight; - } - p = aOut; - - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - - while( p1 && p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - if( iDiff==0 ){ - char *pSave = p; - sqlite3_int64 iPrevSave = iPrev; - int bFirstOutSave = bFirstOut; - - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ - p = pSave; - iPrev = iPrevSave; - bFirstOut = bFirstOutSave; - } - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( iDiff<0 ){ - fts3PoslistCopy(0, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PoslistCopy(0, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - } - - *pnRight = (int)(p - aOut); - if( bDescDoclist ){ - sqlite3_free(aRight); - *paRight = aOut; - } - - return SQLITE_OK; -} - -/* -** Argument pList points to a position list nList bytes in size. This -** function checks to see if the position list contains any entries for -** a token in position 0 (of any column). If so, it writes argument iDelta -** to the output buffer pOut, followed by a position list consisting only -** of the entries from pList at position 0, and terminated by an 0x00 byte. -** The value returned is the number of bytes written to pOut (if any). -*/ -int sqlite3Fts3FirstFilter( - sqlite3_int64 iDelta, /* Varint that may be written to pOut */ - char *pList, /* Position list (no 0x00 term) */ - int nList, /* Size of pList in bytes */ - char *pOut /* Write output here */ -){ - int nOut = 0; - int bWritten = 0; /* True once iDelta has been written */ - char *p = pList; - char *pEnd = &pList[nList]; - - if( *p!=0x01 ){ - if( *p==0x02 ){ - nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta); - pOut[nOut++] = 0x02; - bWritten = 1; - } - fts3ColumnlistCopy(0, &p); - } - - while( paaOutput); i++){ - if( pTS->aaOutput[i] ){ - if( !aOut ){ - aOut = pTS->aaOutput[i]; - nOut = pTS->anOutput[i]; - pTS->aaOutput[i] = 0; - }else{ - int nNew; - char *aNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, - pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - return rc; - } - - sqlite3_free(pTS->aaOutput[i]); - sqlite3_free(aOut); - pTS->aaOutput[i] = 0; - aOut = aNew; - nOut = nNew; - } - } - } - - pTS->aaOutput[0] = aOut; - pTS->anOutput[0] = nOut; - return SQLITE_OK; -} - -/* -** Merge the doclist aDoclist/nDoclist into the TermSelect object passed -** as the first argument. The merge is an "OR" merge (see function -** fts3DoclistOrMerge() for details). -** -** This function is called with the doclist for each term that matches -** a queried prefix. It merges all these doclists into one, the doclist -** for the specified prefix. Since there can be a very large number of -** doclists to merge, the merging is done pair-wise using the TermSelect -** object. -** -** This function returns SQLITE_OK if the merge is successful, or an -** SQLite error code (SQLITE_NOMEM) if an error occurs. -*/ -static int fts3TermSelectMerge( - Fts3Table *p, /* FTS table handle */ - TermSelect *pTS, /* TermSelect object to merge into */ - char *aDoclist, /* Pointer to doclist */ - int nDoclist /* Size of aDoclist in bytes */ -){ - if( pTS->aaOutput[0]==0 ){ - /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). - ** - ** Add FTS3_VARINT_MAX bytes of unused space to the end of the - ** allocation. This is so as to ensure that the buffer is big enough - ** to hold the current doclist AND'd with any other doclist. If the - ** doclists are stored in order=ASC order, this padding would not be - ** required (since the size of [doclistA AND doclistB] is always less - ** than or equal to the size of [doclistA] in that case). But this is - ** not true for order=DESC. For example, a doclist containing (1, -1) - ** may be smaller than (-1), as in the first example the -1 may be stored - ** as a single-byte delta, whereas in the second it must be stored as a - ** FTS3_VARINT_MAX byte varint. - ** - ** Similar padding is added in the fts3DoclistOrMerge() function. - */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); - pTS->anOutput[0] = nDoclist; - if( pTS->aaOutput[0] ){ - memcpy(pTS->aaOutput[0], aDoclist, nDoclist); - memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX); - }else{ - return SQLITE_NOMEM; - } - }else{ - char *aMerge = aDoclist; - int nMerge = nDoclist; - int iOut; - - for(iOut=0; iOutaaOutput); iOut++){ - if( pTS->aaOutput[iOut]==0 ){ - assert( iOut>0 ); - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - break; - }else{ - char *aNew; - int nNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, - pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - return rc; - } - - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - sqlite3_free(pTS->aaOutput[iOut]); - pTS->aaOutput[iOut] = 0; - - aMerge = aNew; - nMerge = nNew; - if( (iOut+1)==SizeofArray(pTS->aaOutput) ){ - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - } - } - } - } - return SQLITE_OK; -} - -/* -** Append SegReader object pNew to the end of the pCsr->apSegment[] array. -*/ -static int fts3SegReaderCursorAppend( - Fts3MultiSegReader *pCsr, - Fts3SegReader *pNew -){ - if( (pCsr->nSegment%16)==0 ){ - Fts3SegReader **apNew; - sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); - apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte); - if( !apNew ){ - sqlite3Fts3SegReaderFree(pNew); - return SQLITE_NOMEM; - } - pCsr->apSegment = apNew; - } - pCsr->apSegment[pCsr->nSegment++] = pNew; - return SQLITE_OK; -} - -/* -** Add seg-reader objects to the Fts3MultiSegReader object passed as the -** 8th argument. -** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -static int fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc = SQLITE_OK; /* Error code */ - sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */ - int rc2; /* Result of sqlite3_reset() */ - - /* If iLevel is less than 0 and this is not a scan, include a seg-reader - ** for the pending-terms. If this is a scan, then this call must be being - ** made by an fts4aux module, not an FTS table. In this case calling - ** Fts3SegReaderPending might segfault, as the data structures used by - ** fts4aux are not completely populated. So it's easiest to filter these - ** calls out here. */ - if( iLevel<0 && p->aIndex ){ - Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); - if( rc==SQLITE_OK && pSeg ){ - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - if( iLevel!=FTS3_SEGCURSOR_PENDING ){ - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); - } - - while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ - Fts3SegReader *pSeg = 0; - - /* Read the values returned by the SELECT into local variables. */ - sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1); - sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2); - sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3); - int nRoot = sqlite3_column_bytes(pStmt, 4); - char const *zRoot = sqlite3_column_blob(pStmt, 4); - - /* If zTerm is not NULL, and this segment is not stored entirely on its - ** root node, the range of leaves scanned can be reduced. Do this. */ - if( iStartBlock && zTerm && zRoot ){ - sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0); - rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi); - if( rc!=SQLITE_OK ) goto finished; - if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock; - } - - rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, - (isPrefix==0 && isScan==0), - iStartBlock, iLeavesEndBlock, - iEndBlock, zRoot, nRoot, &pSeg - ); - if( rc!=SQLITE_OK ) goto finished; - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - finished: - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_DONE ) rc = rc2; - - return rc; -} - -/* -** Set up a cursor object for iterating through a full-text index or a -** single level therein. -*/ -int sqlite3Fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language-id to search */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - assert( iIndex>=0 && iIndexnIndex ); - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevelbase.pVtab; - - if( isPrefix ){ - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr - ); - pSegcsr->bLookup = 1; - } - } - - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm+1 ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr - ); - if( rc==SQLITE_OK ){ - rc = fts3SegReaderCursorAddZero( - p, pCsr->iLangid, zTerm, nTerm, pSegcsr - ); - } - } - } - } - - if( bFound==0 ){ - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr - ); - pSegcsr->bLookup = !isPrefix; - } - } - - *ppSegcsr = pSegcsr; - return rc; -} - -/* -** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor(). -*/ -static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){ - sqlite3Fts3SegReaderFinish(pSegcsr); - sqlite3_free(pSegcsr); -} - -/* -** This function retrieves the doclist for the specified term (or term -** prefix) from the database. -*/ -static int fts3TermSelect( - Fts3Table *p, /* Virtual table handle */ - Fts3PhraseToken *pTok, /* Token to query for */ - int iColumn, /* Column to query (or -ve for all columns) */ - int *pnOut, /* OUT: Size of buffer at *ppOut */ - char **ppOut /* OUT: Malloced result buffer */ -){ - int rc; /* Return code */ - Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */ - TermSelect tsc; /* Object for pair-wise doclist merging */ - Fts3SegFilter filter; /* Segment term filter configuration */ - - pSegcsr = pTok->pSegcsr; - memset(&tsc, 0, sizeof(TermSelect)); - - filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS - | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0) - | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0) - | (iColumnnColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0); - filter.iCol = iColumn; - filter.zTerm = pTok->z; - filter.nTerm = pTok->n; - - rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter); - while( SQLITE_OK==rc - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) - ){ - rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist); - } - - if( rc==SQLITE_OK ){ - rc = fts3TermSelectFinishMerge(p, &tsc); - } - if( rc==SQLITE_OK ){ - *ppOut = tsc.aaOutput[0]; - *pnOut = tsc.anOutput[0]; - }else{ - int i; - for(i=0; ipSegcsr = 0; - return rc; -} - -/* -** This function counts the total number of docids in the doclist stored -** in buffer aList[], size nList bytes. -** -** If the isPoslist argument is true, then it is assumed that the doclist -** contains a position-list following each docid. Otherwise, it is assumed -** that the doclist is simply a list of docids stored as delta encoded -** varints. -*/ -static int fts3DoclistCountDocids(char *aList, int nList){ - int nDoc = 0; /* Return value */ - if( aList ){ - char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */ - char *p = aList; /* Cursor */ - while( peSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){ - if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){ - pCsr->isEof = 1; - rc = sqlite3_reset(pCsr->pStmt); - }else{ - pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0); - rc = SQLITE_OK; - } - }else{ - rc = fts3EvalNext((Fts3Cursor *)pCursor); - } - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** The following are copied from sqliteInt.h. -** -** Constants for the largest and smallest possible 64-bit signed integers. -** These macros are designed to work correctly on both 32-bit and 64-bit -** compilers. -*/ -#ifndef SQLITE_AMALGAMATION -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - -/* -** If the numeric type of argument pVal is "integer", then return it -** converted to a 64-bit signed integer. Otherwise, return a copy of -** the second parameter, iDefault. -*/ -static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){ - if( pVal ){ - int eType = sqlite3_value_numeric_type(pVal); - if( eType==SQLITE_INTEGER ){ - return sqlite3_value_int64(pVal); - } - } - return iDefault; -} - -/* -** This is the xFilter interface for the virtual table. See -** the virtual table xFilter method documentation for additional -** information. -** -** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against -** the %_content table. -** -** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry -** in the %_content table. -** -** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The -** column on the left-hand side of the MATCH operator is column -** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand -** side of the MATCH operator. -*/ -static int fts3FilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc = SQLITE_OK; - char *zSql; /* SQL statement used to access %_content */ - int eSearch; - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - - sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ - sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ - sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ - sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ - int iIdx; - - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - eSearch = (idxNum & 0x0000FFFF); - assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); - assert( p->pSegments==0 ); - - /* Collect arguments into local variables */ - iIdx = 0; - if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; - if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; - assert( iIdx==nVal ); - - /* In case the cursor has been used before, clear it now. */ - fts3ClearCursor(pCsr); - - /* Set the lower and upper bounds on docids to return */ - pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); - pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); - - if( idxStr ){ - pCsr->bDesc = (idxStr[0]=='D'); - }else{ - pCsr->bDesc = p->bDescIdx; - } - pCsr->eSearch = (i16)eSearch; - - if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){ - int iCol = eSearch-FTS3_FULLTEXT_SEARCH; - const char *zQuery = (const char *)sqlite3_value_text(pCons); - - if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - - pCsr->iLangid = 0; - if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid); - - assert( p->base.zErrMsg==0 ); - rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, - p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, - &p->base.zErrMsg - ); - if( rc!=SQLITE_OK ){ - return rc; - } - - rc = fts3EvalStart(pCsr); - sqlite3Fts3SegmentsClose(p); - if( rc!=SQLITE_OK ) return rc; - pCsr->pNextId = pCsr->aDoclist; - pCsr->iPrevId = 0; - } - - /* Compile a SELECT statement for this cursor. For a full-table-scan, the - ** statement loops through all rows of the %_content table. For a - ** full-text query or docid lookup, the statement retrieves a single - ** row by docid. - */ - if( eSearch==FTS3_FULLSCAN_SEARCH ){ - if( pDocidGe || pDocidLe ){ - zSql = sqlite3_mprintf( - "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", - p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, - (pCsr->bDesc ? "DESC" : "ASC") - ); - }else{ - zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); - } - if( zSql ){ - rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); - sqlite3_free(zSql); - }else{ - rc = SQLITE_NOMEM; - } - }else if( eSearch==FTS3_DOCID_SEARCH ){ - rc = fts3CursorSeekStmt(pCsr); - if( rc==SQLITE_OK ){ - rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); - } - } - if( rc!=SQLITE_OK ) return rc; - - return fts3NextMethod(pCursor); -} - -/* -** This is the xEof method of the virtual table. SQLite calls this -** routine to find out if it has reached the end of a result set. -*/ -static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Cursor *pCsr = (Fts3Cursor*)pCursor; - if( pCsr->isEof ){ - fts3ClearCursor(pCsr); - pCsr->isEof = 1; - } - return pCsr->isEof; -} - -/* -** This is the xRowid method. The SQLite core calls this routine to -** retrieve the rowid for the current row of the result set. fts3 -** exposes %_content.docid as the rowid for the virtual table. The -** rowid should be written to *pRowid. -*/ -static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - *pRowid = pCsr->iPrevId; - return SQLITE_OK; -} - -/* -** This is the xColumn method, called by SQLite to request a value from -** the row that the supplied cursor currently points to. -** -** If: -** -** (iCol < p->nColumn) -> The value of the iCol'th user column. -** (iCol == p->nColumn) -> Magic column with the same name as the table. -** (iCol == p->nColumn+1) -> Docid column -** (iCol == p->nColumn+2) -> Langid column -*/ -static int fts3ColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - - /* The column value supplied by SQLite must be in range. */ - assert( iCol>=0 && iCol<=p->nColumn+2 ); - - switch( iCol-p->nColumn ){ - case 0: - /* The special 'table-name' column */ - sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0); - break; - - case 1: - /* The docid column */ - sqlite3_result_int64(pCtx, pCsr->iPrevId); - break; - - case 2: - if( pCsr->pExpr ){ - sqlite3_result_int64(pCtx, pCsr->iLangid); - break; - }else if( p->zLanguageid==0 ){ - sqlite3_result_int(pCtx, 0); - break; - }else{ - iCol = p->nColumn; - /* fall-through */ - } - - default: - /* A user column. Or, if this is a full-table scan, possibly the - ** language-id column. Seek the cursor. */ - rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){ - sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); - } - break; - } - - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** This function is the implementation of the xUpdate callback used by -** FTS3 virtual tables. It is invoked by SQLite each time a row is to be -** inserted, updated or deleted. -*/ -static int fts3UpdateMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid); -} - -/* -** Implementation of xSync() method. Flush the contents of the pending-terms -** hash-table to the database. -*/ -static int fts3SyncMethod(sqlite3_vtab *pVtab){ - - /* Following an incremental-merge operation, assuming that the input - ** segments are not completely consumed (the usual case), they are updated - ** in place to remove the entries that have already been merged. This - ** involves updating the leaf block that contains the smallest unmerged - ** entry and each block (if any) between the leaf and the root node. So - ** if the height of the input segment b-trees is N, and input segments - ** are merged eight at a time, updating the input segments at the end - ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually - ** small - often between 0 and 2. So the overhead of the incremental - ** merge is somewhere between 8 and 24 blocks. To avoid this overhead - ** dwarfing the actual productive work accomplished, the incremental merge - ** is only attempted if it will write at least 64 leaf blocks. Hence - ** nMinMerge. - ** - ** Of course, updating the input segments also involves deleting a bunch - ** of blocks from the segments table. But this is not considered overhead - ** as it would also be required by a crisis-merge that used the same input - ** segments. - */ - const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ - - Fts3Table *p = (Fts3Table*)pVtab; - int rc; - i64 iLastRowid = sqlite3_last_insert_rowid(p->db); - - rc = sqlite3Fts3PendingTermsFlush(p); - if( rc==SQLITE_OK - && p->nLeafAdd>(nMinMerge/16) - && p->nAutoincrmerge && p->nAutoincrmerge!=0xff - ){ - int mxLevel = 0; /* Maximum relative level value in db */ - int A; /* Incr-merge parameter A */ - - rc = sqlite3Fts3MaxLevel(p, &mxLevel); - assert( rc==SQLITE_OK || mxLevel==0 ); - A = p->nLeafAdd * mxLevel; - A += (A/2); - if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); - } - sqlite3Fts3SegmentsClose(p); - sqlite3_set_last_insert_rowid(p->db, iLastRowid); - return rc; -} - -/* -** If it is currently unknown whether or not the FTS table has an %_stat -** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat -** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code -** if an error occurs. -*/ -static int fts3SetHasStat(Fts3Table *p){ - int rc = SQLITE_OK; - if( p->bHasStat==2 ){ - char *zTbl = sqlite3_mprintf("%s_stat", p->zName); - if( zTbl ){ - int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0); - sqlite3_free(zTbl); - p->bHasStat = (res==SQLITE_OK); - }else{ - rc = SQLITE_NOMEM; - } - } - return rc; -} - -/* -** Implementation of xBegin() method. -*/ -static int fts3BeginMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - UNUSED_PARAMETER(pVtab); - assert( p->pSegments==0 ); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=1 ); - TESTONLY( p->inTransaction = 1 ); - TESTONLY( p->mxSavepoint = -1; ); - p->nLeafAdd = 0; - return fts3SetHasStat(p); -} - -/* -** Implementation of xCommit() method. This is a no-op. The contents of -** the pending-terms hash-table have already been flushed into the database -** by fts3SyncMethod(). -*/ -static int fts3CommitMethod(sqlite3_vtab *pVtab){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(pVtab); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=0 ); - assert( p->pSegments==0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** Implementation of xRollback(). Discard the contents of the pending-terms -** hash-table. Any changes made to the database are reverted by SQLite. -*/ -static int fts3RollbackMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - sqlite3Fts3PendingTermsClear(p); - assert( p->inTransaction!=0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** When called, *ppPoslist must point to the byte immediately following the -** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function -** moves *ppPoslist so that it instead points to the first byte of the -** same position list. -*/ -static void fts3ReversePoslist(char *pStart, char **ppPoslist){ - char *p = &(*ppPoslist)[-2]; - char c = 0; - - /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ - while( p>pStart && (c=*p--)==0 ); - - /* Search backwards for a varint with value zero (the end of the previous - ** poslist). This is an 0x00 byte preceded by some byte that does not - ** have the 0x80 bit set. */ - while( p>pStart && (*p & 0x80) | c ){ - c = *p--; - } - assert( p==pStart || c==0 ); - - /* At this point p points to that preceding byte without the 0x80 bit - ** set. So to find the start of the poslist, skip forward 2 bytes then - ** over a varint. - ** - ** Normally. The other case is that p==pStart and the poslist to return - ** is the first in the doclist. In this case do not skip forward 2 bytes. - ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) - ** is required for cases where the first byte of a doclist and the - ** doclist is empty. For example, if the first docid is 10, a doclist - ** that begins with: - ** - ** 0x0A 0x00 - */ - if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } - while( *p++&0x80 ); - *ppPoslist = p; -} - -/* -** Helper function used by the implementation of the overloaded snippet(), -** offsets() and optimize() SQL functions. -** -** If the value passed as the third argument is a blob of size -** sizeof(Fts3Cursor*), then the blob contents are copied to the -** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error -** message is written to context pContext and SQLITE_ERROR returned. The -** string passed via zFunc is used as part of the error message. -*/ -static int fts3FunctionArg( - sqlite3_context *pContext, /* SQL function call context */ - const char *zFunc, /* Function name */ - sqlite3_value *pVal, /* argv[0] passed to function */ - Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ -){ - int rc; - *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor"); - if( (*ppCsr)!=0 ){ - rc = SQLITE_OK; - }else{ - char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); - sqlite3_result_error(pContext, zErr, -1); - sqlite3_free(zErr); - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** Implementation of the snippet() function for FTS3 -*/ -static void fts3SnippetFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of apVal[] array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - const char *zStart = ""; - const char *zEnd = ""; - const char *zEllipsis = "..."; - int iCol = -1; - int nToken = 15; /* Default number of tokens in snippet */ - - /* There must be at least one argument passed to this function (otherwise - ** the non-overloaded version would have been called instead of this one). - */ - assert( nVal>=1 ); - - if( nVal>6 ){ - sqlite3_result_error(pContext, - "wrong number of arguments to function snippet()", -1); - return; - } - if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; - - switch( nVal ){ - case 6: nToken = sqlite3_value_int(apVal[5]); - case 5: iCol = sqlite3_value_int(apVal[4]); - case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); - case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); - case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); - } - if( !zEllipsis || !zEnd || !zStart ){ - sqlite3_result_error_nomem(pContext); - }else if( nToken==0 ){ - sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); - }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); - } -} - -/* -** Implementation of the offsets() function for FTS3 -*/ -static void fts3OffsetsFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; - assert( pCsr ); - if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Offsets(pContext, pCsr); - } -} - -/* -** Implementation of the special optimize() function for FTS3. This -** function merges all segments in the database to a single segment. -** Example usage is: -** -** SELECT optimize(t) FROM t LIMIT 1; -** -** where 't' is the name of an FTS3 table. -*/ -static void fts3OptimizeFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - int rc; /* Return code */ - Fts3Table *p; /* Virtual table handle */ - Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; - p = (Fts3Table *)pCursor->base.pVtab; - assert( p ); - - rc = sqlite3Fts3Optimize(p); - - switch( rc ){ - case SQLITE_OK: - sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC); - break; - case SQLITE_DONE: - sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC); - break; - default: - sqlite3_result_error_code(pContext, rc); - break; - } -} - -/* -** Implementation of the matchinfo() function for FTS3 -*/ -static void fts3MatchinfoFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - assert( nVal==1 || nVal==2 ); - if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ - const char *zArg = 0; - if( nVal>1 ){ - zArg = (const char *)sqlite3_value_text(apVal[1]); - } - sqlite3Fts3Matchinfo(pContext, pCsr, zArg); - } -} - -/* -** This routine implements the xFindFunction method for the FTS3 -** virtual table. -*/ -static int fts3FindFunctionMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Number of SQL function arguments */ - const char *zName, /* Name of SQL function */ - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ - void **ppArg /* Unused */ -){ - struct Overloaded { - const char *zName; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aOverload[] = { - { "snippet", fts3SnippetFunc }, - { "offsets", fts3OffsetsFunc }, - { "optimize", fts3OptimizeFunc }, - { "matchinfo", fts3MatchinfoFunc }, - }; - int i; /* Iterator variable */ - - UNUSED_PARAMETER(pVtab); - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(ppArg); - - for(i=0; idb; /* Database connection */ - int rc; /* Return Code */ - - /* At this point it must be known if the %_stat table exists or not. - ** So bHasStat may not be 2. */ - rc = fts3SetHasStat(p); - - /* As it happens, the pending terms table is always empty here. This is - ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction - ** always opens a savepoint transaction. And the xSavepoint() method - ** flushes the pending terms table. But leave the (no-op) call to - ** PendingTermsFlush() in in case that changes. - */ - assert( p->nPendingData==0 ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3PendingTermsFlush(p); - } - - if( p->zContentTbl==0 ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", - p->zDb, p->zName, zName - ); - } - - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", - p->zDb, p->zName, zName - ); - } - if( p->bHasStat ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", - p->zDb, p->zName, zName - ); - } - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", - p->zDb, p->zName, zName - ); - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", - p->zDb, p->zName, zName - ); - return rc; -} - -/* -** The xSavepoint() method. -** -** Flush the contents of the pending-terms table to disk. -*/ -static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - int rc = SQLITE_OK; - UNUSED_PARAMETER(iSavepoint); - assert( ((Fts3Table *)pVtab)->inTransaction ); - assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint ); - TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); - if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ - rc = fts3SyncMethod(pVtab); - } - return rc; -} - -/* -** The xRelease() method. -** -** This is a no-op. -*/ -static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(iSavepoint); - UNUSED_PARAMETER(pVtab); - assert( p->inTransaction ); - assert( p->mxSavepoint >= iSavepoint ); - TESTONLY( p->mxSavepoint = iSavepoint-1 ); - return SQLITE_OK; -} - -/* -** The xRollbackTo() method. -** -** Discard the contents of the pending terms table. -*/ -static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *p = (Fts3Table*)pVtab; - UNUSED_PARAMETER(iSavepoint); - assert( p->inTransaction ); - TESTONLY( p->mxSavepoint = iSavepoint ); - sqlite3Fts3PendingTermsClear(p); - return SQLITE_OK; -} - -/* -** Return true if zName is the extension on one of the shadow tables used -** by this module. -*/ -static int fts3ShadowName(const char *zName){ - static const char *azName[] = { - "content", "docsize", "segdir", "segments", "stat", - }; - unsigned int i; - for(i=0; ieType==FTSQUERY_PHRASE ){ - int i; - int nToken = pExpr->pPhrase->nToken; - *pnToken += nToken; - for(i=0; ipPhrase->aToken[i]; - int rc = fts3TermSegReaderCursor(pCsr, - pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr - ); - if( rc!=SQLITE_OK ){ - *pRc = rc; - return; - } - } - assert( pExpr->pPhrase->iDoclistToken==0 ); - pExpr->pPhrase->iDoclistToken = -1; - }else{ - *pnOr += (pExpr->eType==FTSQUERY_OR); - fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc); - fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc); - } - } -} - -/* -** Arguments pList/nList contain the doclist for token iToken of phrase p. -** It is merged into the main doclist stored in p->doclist.aAll/nAll. -** -** This function assumes that pList points to a buffer allocated using -** sqlite3_malloc(). This function takes responsibility for eventually -** freeing the buffer. -** -** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. -*/ -static int fts3EvalPhraseMergeToken( - Fts3Table *pTab, /* FTS Table pointer */ - Fts3Phrase *p, /* Phrase to merge pList/nList into */ - int iToken, /* Token pList/nList corresponds to */ - char *pList, /* Pointer to doclist */ - int nList /* Number of bytes in pList */ -){ - int rc = SQLITE_OK; - assert( iToken!=p->iDoclistToken ); - - if( pList==0 ){ - sqlite3_free(p->doclist.aAll); - p->doclist.aAll = 0; - p->doclist.nAll = 0; - } - - else if( p->iDoclistToken<0 ){ - p->doclist.aAll = pList; - p->doclist.nAll = nList; - } - - else if( p->doclist.aAll==0 ){ - sqlite3_free(pList); - } - - else { - char *pLeft; - char *pRight; - int nLeft; - int nRight; - int nDiff; - - if( p->iDoclistTokendoclist.aAll; - nLeft = p->doclist.nAll; - pRight = pList; - nRight = nList; - nDiff = iToken - p->iDoclistToken; - }else{ - pRight = p->doclist.aAll; - nRight = p->doclist.nAll; - pLeft = pList; - nLeft = nList; - nDiff = p->iDoclistToken - iToken; - } - - rc = fts3DoclistPhraseMerge( - pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight - ); - sqlite3_free(pLeft); - p->doclist.aAll = pRight; - p->doclist.nAll = nRight; - } - - if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; - return rc; -} - -/* -** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist -** does not take deferred tokens into account. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseLoad( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p /* Phrase object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int iToken; - int rc = SQLITE_OK; - - for(iToken=0; rc==SQLITE_OK && iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &p->aToken[iToken]; - assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); - - if( pToken->pSegcsr ){ - int nThis = 0; - char *pThis = 0; - rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); - if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); - } - } - assert( pToken->pSegcsr==0 ); - } - - return rc; -} - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -/* -** This function is called on each phrase after the position lists for -** any deferred tokens have been loaded into memory. It updates the phrases -** current position list to include only those positions that are really -** instances of the phrase (after considering deferred tokens). If this -** means that the phrase does not appear in the current row, doclist.pList -** and doclist.nList are both zeroed. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ - int iToken; /* Used to iterate through phrase tokens */ - char *aPoslist = 0; /* Position list for deferred tokens */ - int nPoslist = 0; /* Number of bytes in aPoslist */ - int iPrev = -1; /* Token number of previous deferred token */ - - assert( pPhrase->doclist.bFreeList==0 ); - - for(iToken=0; iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; - Fts3DeferredToken *pDeferred = pToken->pDeferred; - - if( pDeferred ){ - char *pList; - int nList; - int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList); - if( rc!=SQLITE_OK ) return rc; - - if( pList==0 ){ - sqlite3_free(aPoslist); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - - }else if( aPoslist==0 ){ - aPoslist = pList; - nPoslist = nList; - - }else{ - char *aOut = pList; - char *p1 = aPoslist; - char *p2 = aOut; - - assert( iPrev>=0 ); - fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2); - sqlite3_free(aPoslist); - aPoslist = pList; - nPoslist = (int)(aOut - aPoslist); - if( nPoslist==0 ){ - sqlite3_free(aPoslist); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - } - } - iPrev = iToken; - } - } - - if( iPrev>=0 ){ - int nMaxUndeferred = pPhrase->iDoclistToken; - if( nMaxUndeferred<0 ){ - pPhrase->doclist.pList = aPoslist; - pPhrase->doclist.nList = nPoslist; - pPhrase->doclist.iDocid = pCsr->iPrevId; - pPhrase->doclist.bFreeList = 1; - }else{ - int nDistance; - char *p1; - char *p2; - char *aOut; - - if( nMaxUndeferred>iPrev ){ - p1 = aPoslist; - p2 = pPhrase->doclist.pList; - nDistance = nMaxUndeferred - iPrev; - }else{ - p1 = pPhrase->doclist.pList; - p2 = aPoslist; - nDistance = iPrev - nMaxUndeferred; - } - - aOut = (char *)sqlite3_malloc(nPoslist+8); - if( !aOut ){ - sqlite3_free(aPoslist); - return SQLITE_NOMEM; - } - - pPhrase->doclist.pList = aOut; - if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){ - pPhrase->doclist.bFreeList = 1; - pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList); - }else{ - sqlite3_free(aOut); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - } - sqlite3_free(aPoslist); - } - } - - return SQLITE_OK; -} -#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ - -/* -** Maximum number of tokens a phrase may have to be considered for the -** incremental doclists strategy. -*/ -#define MAX_INCR_PHRASE_TOKENS 4 - -/* -** This function is called for each Fts3Phrase in a full-text query -** expression to initialize the mechanism for returning rows. Once this -** function has been called successfully on an Fts3Phrase, it may be -** used with fts3EvalPhraseNext() to iterate through the matching docids. -** -** If parameter bOptOk is true, then the phrase may (or may not) use the -** incremental loading strategy. Otherwise, the entire doclist is loaded into -** memory within this call. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; /* Error code */ - int i; - - /* Determine if doclists may be loaded from disk incrementally. This is - ** possible if the bOptOk argument is true, the FTS doclists will be - ** scanned in forward order, and the phrase consists of - ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" - ** tokens or prefix tokens that cannot use a prefix-index. */ - int bHaveIncr = 0; - int bIncrOk = (bOptOk - && pCsr->bDesc==pTab->bDescIdx - && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 -#ifdef SQLITE_TEST - && pTab->bNoIncrDoclist==0 -#endif - ); - for(i=0; bIncrOk==1 && inToken; i++){ - Fts3PhraseToken *pToken = &p->aToken[i]; - if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ - bIncrOk = 0; - } - if( pToken->pSegcsr ) bHaveIncr = 1; - } - - if( bIncrOk && bHaveIncr ){ - /* Use the incremental approach. */ - int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn); - for(i=0; rc==SQLITE_OK && inToken; i++){ - Fts3PhraseToken *pToken = &p->aToken[i]; - Fts3MultiSegReader *pSegcsr = pToken->pSegcsr; - if( pSegcsr ){ - rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n); - } - } - p->bIncr = 1; - }else{ - /* Load the full doclist for the phrase into memory. */ - rc = fts3EvalPhraseLoad(pCsr, p); - p->bIncr = 0; - } - - assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr ); - return rc; -} - -/* -** This function is used to iterate backwards (from the end to start) -** through doclists. It is used by this module to iterate through phrase -** doclists in reverse and by the fts3_write.c module to iterate through -** pending-terms lists when writing to databases with "order=desc". -** -** The doclist may be sorted in ascending (parameter bDescIdx==0) or -** descending (parameter bDescIdx==1) order of docid. Regardless, this -** function iterates from the end of the doclist to the beginning. -*/ -void sqlite3Fts3DoclistPrev( - int bDescIdx, /* True if the doclist is desc */ - char *aDoclist, /* Pointer to entire doclist */ - int nDoclist, /* Length of aDoclist in bytes */ - char **ppIter, /* IN/OUT: Iterator pointer */ - sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */ - int *pnList, /* OUT: List length pointer */ - u8 *pbEof /* OUT: End-of-file flag */ -){ - char *p = *ppIter; - - assert( nDoclist>0 ); - assert( *pbEof==0 ); - assert( p || *piDocid==0 ); - assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); - - if( p==0 ){ - sqlite3_int64 iDocid = 0; - char *pNext = 0; - char *pDocid = aDoclist; - char *pEnd = &aDoclist[nDoclist]; - int iMul = 1; - - while( pDocid0 ); - assert( *pbEof==0 ); - assert( p || *piDocid==0 ); - assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); - - if( p==0 ){ - p = aDoclist; - p += sqlite3Fts3GetVarint(p, piDocid); - }else{ - fts3PoslistCopy(0, &p); - while( p<&aDoclist[nDoclist] && *p==0 ) p++; - if( p>=&aDoclist[nDoclist] ){ - *pbEof = 1; - }else{ - sqlite3_int64 iVar; - p += sqlite3Fts3GetVarint(p, &iVar); - *piDocid += ((bDescIdx ? -1 : 1) * iVar); - } - } - - *ppIter = p; -} - -/* -** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof -** to true if EOF is reached. -*/ -static void fts3EvalDlPhraseNext( - Fts3Table *pTab, - Fts3Doclist *pDL, - u8 *pbEof -){ - char *pIter; /* Used to iterate through aAll */ - char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */ - - if( pDL->pNextDocid ){ - pIter = pDL->pNextDocid; - }else{ - pIter = pDL->aAll; - } - - if( pIter>=pEnd ){ - /* We have already reached the end of this doclist. EOF. */ - *pbEof = 1; - }else{ - sqlite3_int64 iDelta; - pIter += sqlite3Fts3GetVarint(pIter, &iDelta); - if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){ - pDL->iDocid += iDelta; - }else{ - pDL->iDocid -= iDelta; - } - pDL->pList = pIter; - fts3PoslistCopy(0, &pIter); - pDL->nList = (int)(pIter - pDL->pList); - - /* pIter now points just past the 0x00 that terminates the position- - ** list for document pDL->iDocid. However, if this position-list was - ** edited in place by fts3EvalNearTrim(), then pIter may not actually - ** point to the start of the next docid value. The following line deals - ** with this case by advancing pIter past the zero-padding added by - ** fts3EvalNearTrim(). */ - while( pIterpNextDocid = pIter; - assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter ); - *pbEof = 0; - } -} - -/* -** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext(). -*/ -typedef struct TokenDoclist TokenDoclist; -struct TokenDoclist { - int bIgnore; - sqlite3_int64 iDocid; - char *pList; - int nList; -}; - -/* -** Token pToken is an incrementally loaded token that is part of a -** multi-token phrase. Advance it to the next matching document in the -** database and populate output variable *p with the details of the new -** entry. Or, if the iterator has reached EOF, set *pbEof to true. -** -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -*/ -static int incrPhraseTokenNext( - Fts3Table *pTab, /* Virtual table handle */ - Fts3Phrase *pPhrase, /* Phrase to advance token of */ - int iToken, /* Specific token to advance */ - TokenDoclist *p, /* OUT: Docid and doclist for new entry */ - u8 *pbEof /* OUT: True if iterator is at EOF */ -){ - int rc = SQLITE_OK; - - if( pPhrase->iDoclistToken==iToken ){ - assert( p->bIgnore==0 ); - assert( pPhrase->aToken[iToken].pSegcsr==0 ); - fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof); - p->pList = pPhrase->doclist.pList; - p->nList = pPhrase->doclist.nList; - p->iDocid = pPhrase->doclist.iDocid; - }else{ - Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; - assert( pToken->pDeferred==0 ); - assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 ); - if( pToken->pSegcsr ){ - assert( p->bIgnore==0 ); - rc = sqlite3Fts3MsrIncrNext( - pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList - ); - if( p->pList==0 ) *pbEof = 1; - }else{ - p->bIgnore = 1; - } - } - - return rc; -} - - -/* -** The phrase iterator passed as the second argument: -** -** * features at least one token that uses an incremental doclist, and -** -** * does not contain any deferred tokens. -** -** Advance it to the next matching documnent in the database and populate -** the Fts3Doclist.pList and nList fields. -** -** If there is no "next" entry and no error occurs, then *pbEof is set to -** 1 before returning. Otherwise, if no error occurs and the iterator is -** successfully advanced, *pbEof is set to 0. -** -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -*/ -static int fts3EvalIncrPhraseNext( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p, /* Phrase object to advance to next docid */ - u8 *pbEof /* OUT: Set to 1 if EOF */ -){ - int rc = SQLITE_OK; - Fts3Doclist *pDL = &p->doclist; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - u8 bEof = 0; - - /* This is only called if it is guaranteed that the phrase has at least - ** one incremental token. In which case the bIncr flag is set. */ - assert( p->bIncr==1 ); - - if( p->nToken==1 ){ - rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, - &pDL->iDocid, &pDL->pList, &pDL->nList - ); - if( pDL->pList==0 ) bEof = 1; - }else{ - int bDescDoclist = pCsr->bDesc; - struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS]; - - memset(a, 0, sizeof(a)); - assert( p->nToken<=MAX_INCR_PHRASE_TOKENS ); - assert( p->iDoclistTokennToken && bEof==0; i++){ - rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); - if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){ - iMax = a[i].iDocid; - bMaxSet = 1; - } - } - assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) ); - assert( rc!=SQLITE_OK || bMaxSet ); - - /* Keep advancing iterators until they all point to the same document */ - for(i=0; inToken; i++){ - while( rc==SQLITE_OK && bEof==0 - && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 - ){ - rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); - if( DOCID_CMP(a[i].iDocid, iMax)>0 ){ - iMax = a[i].iDocid; - i = 0; - } - } - } - - /* Check if the current entries really are a phrase match */ - if( bEof==0 ){ - int nList = 0; - int nByte = a[p->nToken-1].nList; - char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING); - if( !aDoclist ) return SQLITE_NOMEM; - memcpy(aDoclist, a[p->nToken-1].pList, nByte+1); - memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING); - - for(i=0; i<(p->nToken-1); i++){ - if( a[i].bIgnore==0 ){ - char *pL = a[i].pList; - char *pR = aDoclist; - char *pOut = aDoclist; - int nDist = p->nToken-1-i; - int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR); - if( res==0 ) break; - nList = (int)(pOut - aDoclist); - } - } - if( i==(p->nToken-1) ){ - pDL->iDocid = iMax; - pDL->pList = aDoclist; - pDL->nList = nList; - pDL->bFreeList = 1; - break; - } - sqlite3_free(aDoclist); - } - } - } - - *pbEof = bEof; - return rc; -} - -/* -** Attempt to move the phrase iterator to point to the next matching docid. -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -** -** If there is no "next" entry and no error occurs, then *pbEof is set to -** 1 before returning. Otherwise, if no error occurs and the iterator is -** successfully advanced, *pbEof is set to 0. -*/ -static int fts3EvalPhraseNext( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p, /* Phrase object to advance to next docid */ - u8 *pbEof /* OUT: Set to 1 if EOF */ -){ - int rc = SQLITE_OK; - Fts3Doclist *pDL = &p->doclist; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - - if( p->bIncr ){ - rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof); - }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){ - sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, - &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof - ); - pDL->pList = pDL->pNextDocid; - }else{ - fts3EvalDlPhraseNext(pTab, pDL, pbEof); - } - - return rc; -} - -/* -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, fts3EvalPhraseStart() is called on all phrases within the -** expression. Also the Fts3Expr.bDeferred variable is set to true for any -** expressions for which all descendent tokens are deferred. -** -** If parameter bOptOk is zero, then it is guaranteed that the -** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for -** each phrase in the expression (subject to deferred token processing). -** Or, if bOptOk is non-zero, then one or more tokens within the expression -** may be loaded incrementally, meaning doclist.aAll/nAll is not available. -** -** If an error occurs within this function, *pRc is set to an SQLite error -** code before returning. -*/ -static void fts3EvalStartReaders( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expression to initialize phrases in */ - int *pRc /* IN/OUT: Error code */ -){ - if( pExpr && SQLITE_OK==*pRc ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - int nToken = pExpr->pPhrase->nToken; - if( nToken ){ - int i; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; - } - pExpr->bDeferred = (i==nToken); - } - *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); - }else{ - fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); - fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); - pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); - } - } -} - -/* -** An array of the following structures is assembled as part of the process -** of selecting tokens to defer before the query starts executing (as part -** of the xFilter() method). There is one element in the array for each -** token in the FTS expression. -** -** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong -** to phrases that are connected only by AND and NEAR operators (not OR or -** NOT). When determining tokens to defer, each AND/NEAR cluster is considered -** separately. The root of a tokens AND/NEAR cluster is stored in -** Fts3TokenAndCost.pRoot. -*/ -typedef struct Fts3TokenAndCost Fts3TokenAndCost; -struct Fts3TokenAndCost { - Fts3Phrase *pPhrase; /* The phrase the token belongs to */ - int iToken; /* Position of token in phrase */ - Fts3PhraseToken *pToken; /* The token itself */ - Fts3Expr *pRoot; /* Root of NEAR/AND cluster */ - int nOvfl; /* Number of overflow pages to load doclist */ - int iCol; /* The column the token must match */ -}; - -/* -** This function is used to populate an allocated Fts3TokenAndCost array. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if an error occurs during execution, *pRc is set to an -** SQLite error code. -*/ -static void fts3EvalTokenCosts( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */ - Fts3Expr *pExpr, /* Expression to consider */ - Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */ - Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - for(i=0; *pRc==SQLITE_OK && inToken; i++){ - Fts3TokenAndCost *pTC = (*ppTC)++; - pTC->pPhrase = pPhrase; - pTC->iToken = i; - pTC->pRoot = pRoot; - pTC->pToken = &pPhrase->aToken[i]; - pTC->iCol = pPhrase->iColumn; - *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl); - } - }else if( pExpr->eType!=FTSQUERY_NOT ){ - assert( pExpr->eType==FTSQUERY_OR - || pExpr->eType==FTSQUERY_AND - || pExpr->eType==FTSQUERY_NEAR - ); - assert( pExpr->pLeft && pExpr->pRight ); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pLeft; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pRight; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc); - } - } -} - -/* -** Determine the average document (row) size in pages. If successful, -** write this value to *pnPage and return SQLITE_OK. Otherwise, return -** an SQLite error code. -** -** The average document size in pages is calculated by first calculating -** determining the average size in bytes, B. If B is less than the amount -** of data that will fit on a single leaf page of an intkey table in -** this database, then the average docsize is 1. Otherwise, it is 1 plus -** the number of overflow pages consumed by a record B bytes in size. -*/ -static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ - int rc = SQLITE_OK; - if( pCsr->nRowAvg==0 ){ - /* The average document size, which is required to calculate the cost - ** of each doclist, has not yet been determined. Read the required - ** data from the %_stat table to calculate it. - ** - ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 - ** varints, where nCol is the number of columns in the FTS3 table. - ** The first varint is the number of documents currently stored in - ** the table. The following nCol varints contain the total amount of - ** data stored in all rows of each column of the table, from left - ** to right. - */ - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - sqlite3_stmt *pStmt; - sqlite3_int64 nDoc = 0; - sqlite3_int64 nByte = 0; - const char *pEnd; - const char *a; - - rc = sqlite3Fts3SelectDoctotal(p, &pStmt); - if( rc!=SQLITE_OK ) return rc; - a = sqlite3_column_blob(pStmt, 0); - assert( a ); - - pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; - a += sqlite3Fts3GetVarint(a, &nDoc); - while( anDoc = nDoc; - pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz); - assert( pCsr->nRowAvg>0 ); - rc = sqlite3_reset(pStmt); - } - - *pnPage = pCsr->nRowAvg; - return rc; -} - -/* -** This function is called to select the tokens (if any) that will be -** deferred. The array aTC[] has already been populated when this is -** called. -** -** This function is called once for each AND/NEAR cluster in the -** expression. Each invocation determines which tokens to defer within -** the cluster with root node pRoot. See comments above the definition -** of struct Fts3TokenAndCost for more details. -** -** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken() -** called on each token to defer. Otherwise, an SQLite error code is -** returned. -*/ -static int fts3EvalSelectDeferred( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Consider tokens with this root node */ - Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */ - int nTC /* Number of entries in aTC[] */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int nDocSize = 0; /* Number of pages per doc loaded */ - int rc = SQLITE_OK; /* Return code */ - int ii; /* Iterator variable for various purposes */ - int nOvfl = 0; /* Total overflow pages used by doclists */ - int nToken = 0; /* Total number of tokens in cluster */ - - int nMinEst = 0; /* The minimum count for any phrase so far. */ - int nLoad4 = 1; /* (Phrases that will be loaded)^4. */ - - /* Tokens are never deferred for FTS tables created using the content=xxx - ** option. The reason being that it is not guaranteed that the content - ** table actually contains the same data as the index. To prevent this from - ** causing any problems, the deferred token optimization is completely - ** disabled for content=xxx tables. */ - if( pTab->zContentTbl ){ - return SQLITE_OK; - } - - /* Count the tokens in this AND/NEAR cluster. If none of the doclists - ** associated with the tokens spill onto overflow pages, or if there is - ** only 1 token, exit early. No tokens to defer in this case. */ - for(ii=0; ii0 ); - - - /* Iterate through all tokens in this AND/NEAR cluster, in ascending order - ** of the number of overflow pages that will be loaded by the pager layer - ** to retrieve the entire doclist for the token from the full-text index. - ** Load the doclists for tokens that are either: - ** - ** a. The cheapest token in the entire query (i.e. the one visited by the - ** first iteration of this loop), or - ** - ** b. Part of a multi-token phrase. - ** - ** After each token doclist is loaded, merge it with the others from the - ** same phrase and count the number of documents that the merged doclist - ** contains. Set variable "nMinEst" to the smallest number of documents in - ** any phrase doclist for which 1 or more token doclists have been loaded. - ** Let nOther be the number of other phrases for which it is certain that - ** one or more tokens will not be deferred. - ** - ** Then, for each token, defer it if loading the doclist would result in - ** loading N or more overflow pages into memory, where N is computed as: - ** - ** (nMinEst + 4^nOther - 1) / (4^nOther) - */ - for(ii=0; iinOvfl) - ){ - pTC = &aTC[iTC]; - } - } - assert( pTC ); - - if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){ - /* The number of overflow pages to load for this (and therefore all - ** subsequent) tokens is greater than the estimated number of pages - ** that will be loaded if all subsequent tokens are deferred. - */ - Fts3PhraseToken *pToken = pTC->pToken; - rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol); - fts3SegReaderCursorFree(pToken->pSegcsr); - pToken->pSegcsr = 0; - }else{ - /* Set nLoad4 to the value of (4^nOther) for the next iteration of the - ** for-loop. Except, limit the value to 2^24 to prevent it from - ** overflowing the 32-bit integer it is stored in. */ - if( ii<12 ) nLoad4 = nLoad4*4; - - if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ - /* Either this is the cheapest token in the entire query, or it is - ** part of a multi-token phrase. Either way, the entire doclist will - ** (eventually) be loaded into memory. It may as well be now. */ - Fts3PhraseToken *pToken = pTC->pToken; - int nList = 0; - char *pList = 0; - rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); - assert( rc==SQLITE_OK || pList==0 ); - if( rc==SQLITE_OK ){ - rc = fts3EvalPhraseMergeToken( - pTab, pTC->pPhrase, pTC->iToken,pList,nList - ); - } - if( rc==SQLITE_OK ){ - int nCount; - nCount = fts3DoclistCountDocids( - pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll - ); - if( ii==0 || nCountpToken = 0; - } - - return rc; -} - -/* -** This function is called from within the xFilter method. It initializes -** the full-text query currently stored in pCsr->pExpr. To iterate through -** the results of a query, the caller does: -** -** fts3EvalStart(pCsr); -** while( 1 ){ -** fts3EvalNext(pCsr); -** if( pCsr->bEof ) break; -** ... return row pCsr->iPrevId to the caller ... -** } -*/ -static int fts3EvalStart(Fts3Cursor *pCsr){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int nToken = 0; - int nOr = 0; - - /* Allocate a MultiSegReader for each token in the expression. */ - fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc); - - /* Determine which, if any, tokens in the expression should be deferred. */ -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ - Fts3TokenAndCost *aTC; - Fts3Expr **apOr; - aTC = (Fts3TokenAndCost *)sqlite3_malloc64( - sizeof(Fts3TokenAndCost) * nToken - + sizeof(Fts3Expr *) * nOr * 2 - ); - apOr = (Fts3Expr **)&aTC[nToken]; - - if( !aTC ){ - rc = SQLITE_NOMEM; - }else{ - int ii; - Fts3TokenAndCost *pTC = aTC; - Fts3Expr **ppOr = apOr; - - fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc); - nToken = (int)(pTC-aTC); - nOr = (int)(ppOr-apOr); - - if( rc==SQLITE_OK ){ - rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken); - for(ii=0; rc==SQLITE_OK && iipExpr, &rc); - return rc; -} - -/* -** Invalidate the current position list for phrase pPhrase. -*/ -static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){ - if( pPhrase->doclist.bFreeList ){ - sqlite3_free(pPhrase->doclist.pList); - } - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - pPhrase->doclist.bFreeList = 0; -} - -/* -** This function is called to edit the position list associated with -** the phrase object passed as the fifth argument according to a NEAR -** condition. For example: -** -** abc NEAR/5 "def ghi" -** -** Parameter nNear is passed the NEAR distance of the expression (5 in -** the example above). When this function is called, *paPoslist points to -** the position list, and *pnToken is the number of phrase tokens in, the -** phrase on the other side of the NEAR operator to pPhrase. For example, -** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to -** the position list associated with phrase "abc". -** -** All positions in the pPhrase position list that are not sufficiently -** close to a position in the *paPoslist position list are removed. If this -** leaves 0 positions, zero is returned. Otherwise, non-zero. -** -** Before returning, *paPoslist is set to point to the position lsit -** associated with pPhrase. And *pnToken is set to the number of tokens in -** pPhrase. -*/ -static int fts3EvalNearTrim( - int nNear, /* NEAR distance. As in "NEAR/nNear". */ - char *aTmp, /* Temporary space to use */ - char **paPoslist, /* IN/OUT: Position list */ - int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */ - Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */ -){ - int nParam1 = nNear + pPhrase->nToken; - int nParam2 = nNear + *pnToken; - int nNew; - char *p2; - char *pOut; - int res; - - assert( pPhrase->doclist.pList ); - - p2 = pOut = pPhrase->doclist.pList; - res = fts3PoslistNearMerge( - &pOut, aTmp, nParam1, nParam2, paPoslist, &p2 - ); - if( res ){ - nNew = (int)(pOut - pPhrase->doclist.pList) - 1; - assert( pPhrase->doclist.pList[nNew]=='\0' ); - assert( nNew<=pPhrase->doclist.nList && nNew>0 ); - memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); - pPhrase->doclist.nList = nNew; - *paPoslist = pPhrase->doclist.pList; - *pnToken = pPhrase->nToken; - } - - return res; -} - -/* -** This function is a no-op if *pRc is other than SQLITE_OK when it is called. -** Otherwise, it advances the expression passed as the second argument to -** point to the next matching row in the database. Expressions iterate through -** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero, -** or descending if it is non-zero. -** -** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if -** successful, the following variables in pExpr are set: -** -** Fts3Expr.bEof (non-zero if EOF - there is no next row) -** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row) -** -** If the expression is of type FTSQUERY_PHRASE, and the expression is not -** at EOF, then the following variables are populated with the position list -** for the phrase for the visited row: -** -** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes) -** FTs3Expr.pPhrase->doclist.pList (pointer to position list) -** -** It says above that this function advances the expression to the next -** matching row. This is usually true, but there are the following exceptions: -** -** 1. Deferred tokens are not taken into account. If a phrase consists -** entirely of deferred tokens, it is assumed to match every row in -** the db. In this case the position-list is not populated at all. -** -** Or, if a phrase contains one or more deferred tokens and one or -** more non-deferred tokens, then the expression is advanced to the -** next possible match, considering only non-deferred tokens. In other -** words, if the phrase is "A B C", and "B" is deferred, the expression -** is advanced to the next row that contains an instance of "A * C", -** where "*" may match any single token. The position list in this case -** is populated as for "A * C" before returning. -** -** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is -** advanced to point to the next row that matches "x AND y". -** -** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is -** really a match, taking into account deferred tokens and NEAR operators. -*/ -static void fts3EvalNextRow( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expr. to advance to next matching row */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ - assert( pExpr->bEof==0 ); - pExpr->bStart = 1; - - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - assert( !pLeft->bDeferred || !pRight->bDeferred ); - - if( pLeft->bDeferred ){ - /* LHS is entirely deferred. So we assume it matches every row. - ** Advance the RHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pRight, pRc); - pExpr->iDocid = pRight->iDocid; - pExpr->bEof = pRight->bEof; - }else if( pRight->bDeferred ){ - /* RHS is entirely deferred. So we assume it matches every row. - ** Advance the LHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - }else{ - /* Neither the RHS or LHS are deferred. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){ - sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( iDiff==0 ) break; - if( iDiff<0 ){ - fts3EvalNextRow(pCsr, pLeft, pRc); - }else{ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = (pLeft->bEof || pRight->bEof); - if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){ - assert( pRight->eType==FTSQUERY_PHRASE ); - if( pRight->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pRight->pPhrase->doclist; - while( *pRc==SQLITE_OK && pRight->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - if( pLeft->pPhrase && pLeft->pPhrase->doclist.aAll ){ - Fts3Doclist *pDl = &pLeft->pPhrase->doclist; - while( *pRc==SQLITE_OK && pLeft->bEof==0 ){ - memset(pDl->pList, 0, pDl->nList); - fts3EvalNextRow(pCsr, pLeft, pRc); - } - } - } - } - break; - } - - case FTSQUERY_OR: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - - assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); - assert( pRight->bStart || pLeft->iDocid==pRight->iDocid ); - - if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ - fts3EvalNextRow(pCsr, pLeft, pRc); - }else if( pLeft->bEof || iCmp>0 ){ - fts3EvalNextRow(pCsr, pRight, pRc); - }else{ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - } - - pExpr->bEof = (pLeft->bEof && pRight->bEof); - iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ - pExpr->iDocid = pLeft->iDocid; - }else{ - pExpr->iDocid = pRight->iDocid; - } - - break; - } - - case FTSQUERY_NOT: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - - if( pRight->bStart==0 ){ - fts3EvalNextRow(pCsr, pRight, pRc); - assert( *pRc!=SQLITE_OK || pRight->bStart ); - } - - fts3EvalNextRow(pCsr, pLeft, pRc); - if( pLeft->bEof==0 ){ - while( !*pRc - && !pRight->bEof - && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 - ){ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - break; - } - - default: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - fts3EvalInvalidatePoslist(pPhrase); - *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof); - pExpr->iDocid = pPhrase->doclist.iDocid; - break; - } - } - } -} - -/* -** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR -** cluster, then this function returns 1 immediately. -** -** Otherwise, it checks if the current row really does match the NEAR -** expression, using the data currently stored in the position lists -** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. -** -** If the current row is a match, the position list associated with each -** phrase in the NEAR expression is edited in place to contain only those -** phrase instances sufficiently close to their peers to satisfy all NEAR -** constraints. In this case it returns 1. If the NEAR expression does not -** match the current row, 0 is returned. The position lists may or may not -** be edited if 0 is returned. -*/ -static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ - int res = 1; - - /* The following block runs if pExpr is the root of a NEAR query. - ** For example, the query: - ** - ** "w" NEAR "x" NEAR "y" NEAR "z" - ** - ** which is represented in tree form as: - ** - ** | - ** +--NEAR--+ <-- root of NEAR query - ** | | - ** +--NEAR--+ "z" - ** | | - ** +--NEAR--+ "y" - ** | | - ** "w" "x" - ** - ** The right-hand child of a NEAR node is always a phrase. The - ** left-hand child may be either a phrase or a NEAR node. There are - ** no exceptions to this - it's the way the parser in fts3_expr.c works. - */ - if( *pRc==SQLITE_OK - && pExpr->eType==FTSQUERY_NEAR - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - sqlite3_int64 nTmp = 0; /* Bytes of temp space */ - char *aTmp; /* Temp space for PoslistNearMerge() */ - - /* Allocate temporary working space. */ - for(p=pExpr; p->pLeft; p=p->pLeft){ - assert( p->pRight->pPhrase->doclist.nList>0 ); - nTmp += p->pRight->pPhrase->doclist.nList; - } - nTmp += p->pPhrase->doclist.nList; - aTmp = sqlite3_malloc64(nTmp*2); - if( !aTmp ){ - *pRc = SQLITE_NOMEM; - res = 0; - }else{ - char *aPoslist = p->pPhrase->doclist.pList; - int nToken = p->pPhrase->nToken; - - for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ - Fts3Phrase *pPhrase = p->pRight->pPhrase; - int nNear = p->nNear; - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - - aPoslist = pExpr->pRight->pPhrase->doclist.pList; - nToken = pExpr->pRight->pPhrase->nToken; - for(p=pExpr->pLeft; p && res; p=p->pLeft){ - int nNear; - Fts3Phrase *pPhrase; - assert( p->pParent && p->pParent->pLeft==p ); - nNear = p->pParent->nNear; - pPhrase = ( - p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase - ); - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - } - - sqlite3_free(aTmp); - } - - return res; -} - -/* -** This function is a helper function for sqlite3Fts3EvalTestDeferred(). -** Assuming no error occurs or has occurred, It returns non-zero if the -** expression passed as the second argument matches the row that pCsr -** currently points to, or zero if it does not. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** If an error occurs during execution of this function, *pRc is set to -** the appropriate SQLite error code. In this case the returned value is -** undefined. -*/ -static int fts3EvalTestExpr( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Expr to test. May or may not be root. */ - int *pRc /* IN/OUT: Error code */ -){ - int bHit = 1; /* Return value */ - if( *pRc==SQLITE_OK ){ - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - && fts3EvalNearTest(pExpr, pRc) - ); - - /* If the NEAR expression does not match any rows, zero the doclist for - ** all phrases involved in the NEAR. This is because the snippet(), - ** offsets() and matchinfo() functions are not supposed to recognize - ** any instances of phrases that are part of unmatched NEAR queries. - ** For example if this expression: - ** - ** ... MATCH 'a OR (b NEAR c)' - ** - ** is matched against a row containing: - ** - ** 'a b d e' - ** - ** then any snippet() should ony highlight the "a" term, not the "b" - ** (as "b" is part of a non-matching NEAR clause). - */ - if( bHit==0 - && pExpr->eType==FTSQUERY_NEAR - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - for(p=pExpr; p->pPhrase==0; p=p->pLeft){ - if( p->pRight->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pRight->pPhrase); - } - } - if( p->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pPhrase); - } - } - - break; - - case FTSQUERY_OR: { - int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc); - int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc); - bHit = bHit1 || bHit2; - break; - } - - case FTSQUERY_NOT: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - ); - break; - - default: { -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( pCsr->pDeferred - && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred) - ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 ); - if( pExpr->bDeferred ){ - fts3EvalInvalidatePoslist(pPhrase); - } - *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase); - bHit = (pPhrase->doclist.pList!=0); - pExpr->iDocid = pCsr->iPrevId; - }else -#endif - { - bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId); - } - break; - } - } - } - return bHit; -} - -/* -** This function is called as the second part of each xNext operation when -** iterating through the results of a full-text query. At this point the -** cursor points to a row that matches the query expression, with the -** following caveats: -** -** * Up until this point, "NEAR" operators in the expression have been -** treated as "AND". -** -** * Deferred tokens have not yet been considered. -** -** If *pRc is not SQLITE_OK when this function is called, it immediately -** returns 0. Otherwise, it tests whether or not after considering NEAR -** operators and deferred tokens the current row is still a match for the -** expression. It returns 1 if both of the following are true: -** -** 1. *pRc is SQLITE_OK when this function returns, and -** -** 2. After scanning the current FTS table row for the deferred tokens, -** it is determined that the row does *not* match the query. -** -** Or, if no error occurs and it seems the current row does match the FTS -** query, return 0. -*/ -int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ - int rc = *pRc; - int bMiss = 0; - if( rc==SQLITE_OK ){ - - /* If there are one or more deferred tokens, load the current row into - ** memory and scan it to determine the position list for each deferred - ** token. Then, see if this row is really a match, considering deferred - ** tokens and NEAR operators (neither of which were taken into account - ** earlier, by fts3EvalNextRow()). - */ - if( pCsr->pDeferred ){ - rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3CacheDeferredDoclists(pCsr); - } - } - bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc)); - - /* Free the position-lists accumulated for each deferred token above. */ - sqlite3Fts3FreeDeferredDoclists(pCsr); - *pRc = rc; - } - return (rc==SQLITE_OK && bMiss); -} - -/* -** Advance to the next document that matches the FTS expression in -** Fts3Cursor.pExpr. -*/ -static int fts3EvalNext(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Expr *pExpr = pCsr->pExpr; - assert( pCsr->isEof==0 ); - if( pExpr==0 ){ - pCsr->isEof = 1; - }else{ - do { - if( pCsr->isRequireSeek==0 ){ - sqlite3_reset(pCsr->pStmt); - } - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - fts3EvalNextRow(pCsr, pExpr, &rc); - pCsr->isEof = pExpr->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pExpr->iDocid; - }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); - } - - /* Check if the cursor is past the end of the docid range specified - ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ - if( rc==SQLITE_OK && ( - (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) - || (pCsr->bDesc!=0 && pCsr->iPrevIdiMinDocid) - )){ - pCsr->isEof = 1; - } - - return rc; -} - -/* -** Restart interation for expression pExpr so that the next call to -** fts3EvalNext() visits the first row. Do not allow incremental -** loading or merging of phrase doclists for this iteration. -** -** If *pRc is other than SQLITE_OK when this function is called, it is -** a no-op. If an error occurs within this function, *pRc is set to an -** SQLite error code before returning. -*/ -static void fts3EvalRestart( - Fts3Cursor *pCsr, - Fts3Expr *pExpr, - int *pRc -){ - if( pExpr && *pRc==SQLITE_OK ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - - if( pPhrase ){ - fts3EvalInvalidatePoslist(pPhrase); - if( pPhrase->bIncr ){ - int i; - for(i=0; inToken; i++){ - Fts3PhraseToken *pToken = &pPhrase->aToken[i]; - assert( pToken->pDeferred==0 ); - if( pToken->pSegcsr ){ - sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); - } - } - *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); - } - pPhrase->doclist.pNextDocid = 0; - pPhrase->doclist.iDocid = 0; - pPhrase->pOrPoslist = 0; - } - - pExpr->iDocid = 0; - pExpr->bEof = 0; - pExpr->bStart = 0; - - fts3EvalRestart(pCsr, pExpr->pLeft, pRc); - fts3EvalRestart(pCsr, pExpr->pRight, pRc); - } -} - -/* -** After allocating the Fts3Expr.aMI[] array for each phrase in the -** expression rooted at pExpr, the cursor iterates through all rows matched -** by pExpr, calling this function for each row. This function increments -** the values in Fts3Expr.aMI[] according to the position-list currently -** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase -** expression nodes. -*/ -static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){ - if( pExpr ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - if( pPhrase && pPhrase->doclist.pList ){ - int iCol = 0; - char *p = pPhrase->doclist.pList; - - do{ - u8 c = 0; - int iCnt = 0; - while( 0xFE & (*p | c) ){ - if( (c&0x80)==0 ) iCnt++; - c = *p++ & 0x80; - } - - /* aMI[iCol*3 + 1] = Number of occurrences - ** aMI[iCol*3 + 2] = Number of rows containing at least one instance - */ - pExpr->aMI[iCol*3 + 1] += iCnt; - pExpr->aMI[iCol*3 + 2] += (iCnt>0); - if( *p==0x00 ) break; - p++; - p += fts3GetVarint32(p, &iCol); - }while( iColpLeft, nCol); - fts3EvalUpdateCounts(pExpr->pRight, nCol); - } -} - -/* -** Expression pExpr must be of type FTSQUERY_PHRASE. -** -** If it is not already allocated and populated, this function allocates and -** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part -** of a NEAR expression, then it also allocates and populates the same array -** for all other phrases that are part of the NEAR expression. -** -** SQLITE_OK is returned if the aMI[] array is successfully allocated and -** populated. Otherwise, if an error occurs, an SQLite error code is returned. -*/ -static int fts3EvalGatherStats( - Fts3Cursor *pCsr, /* Cursor object */ - Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( pExpr->eType==FTSQUERY_PHRASE ); - if( pExpr->aMI==0 ){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - Fts3Expr *pRoot; /* Root of NEAR expression */ - Fts3Expr *p; /* Iterator used for several purposes */ - - sqlite3_int64 iPrevId = pCsr->iPrevId; - sqlite3_int64 iDocid; - u8 bEof; - - /* Find the root of the NEAR expression */ - pRoot = pExpr; - while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){ - pRoot = pRoot->pParent; - } - iDocid = pRoot->iDocid; - bEof = pRoot->bEof; - assert( pRoot->bStart ); - - /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */ - for(p=pRoot; p; p=p->pLeft){ - Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight); - assert( pE->aMI==0 ); - pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32)); - if( !pE->aMI ) return SQLITE_NOMEM; - memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); - } - - fts3EvalRestart(pCsr, pRoot, &rc); - - while( pCsr->isEof==0 && rc==SQLITE_OK ){ - - do { - /* Ensure the %_content statement is reset. */ - if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt); - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - - /* Advance to the next document */ - fts3EvalNextRow(pCsr, pRoot, &rc); - pCsr->isEof = pRoot->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pRoot->iDocid; - }while( pCsr->isEof==0 - && pRoot->eType==FTSQUERY_NEAR - && sqlite3Fts3EvalTestDeferred(pCsr, &rc) - ); - - if( rc==SQLITE_OK && pCsr->isEof==0 ){ - fts3EvalUpdateCounts(pRoot, pTab->nColumn); - } - } - - pCsr->isEof = 0; - pCsr->iPrevId = iPrevId; - - if( bEof ){ - pRoot->bEof = bEof; - }else{ - /* Caution: pRoot may iterate through docids in ascending or descending - ** order. For this reason, even though it seems more defensive, the - ** do loop can not be written: - ** - ** do {...} while( pRoot->iDocidbEof==0 ); - }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); - } - } - return rc; -} - -/* -** This function is used by the matchinfo() module to query a phrase -** expression node for the following information: -** -** 1. The total number of occurrences of the phrase in each column of -** the FTS table (considering all rows), and -** -** 2. For each column, the number of rows in the table for which the -** column contains at least one instance of the phrase. -** -** If no error occurs, SQLITE_OK is returned and the values for each column -** written into the array aiOut as follows: -** -** aiOut[iCol*3 + 1] = Number of occurrences -** aiOut[iCol*3 + 2] = Number of rows containing at least one instance -** -** Caveats: -** -** * If a phrase consists entirely of deferred tokens, then all output -** values are set to the number of documents in the table. In other -** words we assume that very common tokens occur exactly once in each -** column of each row of the table. -** -** * If a phrase contains some deferred tokens (and some non-deferred -** tokens), count the potential occurrence identified by considering -** the non-deferred tokens instead of actual phrase occurrences. -** -** * If the phrase is part of a NEAR expression, then only phrase instances -** that meet the NEAR constraint are included in the counts. -*/ -int sqlite3Fts3EvalPhraseStats( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Phrase expression */ - u32 *aiOut /* Array to write results into (see above) */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int iCol; - - if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){ - assert( pCsr->nDoc>0 ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = (u32)pCsr->nDoc; - aiOut[iCol*3 + 2] = (u32)pCsr->nDoc; - } - }else{ - rc = fts3EvalGatherStats(pCsr, pExpr); - if( rc==SQLITE_OK ){ - assert( pExpr->aMI ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1]; - aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2]; - } - } - } - - return rc; -} - -/* -** The expression pExpr passed as the second argument to this function -** must be of type FTSQUERY_PHRASE. -** -** The returned value is either NULL or a pointer to a buffer containing -** a position-list indicating the occurrences of the phrase in column iCol -** of the current row. -** -** More specifically, the returned buffer contains 1 varint for each -** occurrence of the phrase in the column, stored using the normal (delta+2) -** compression and is terminated by either an 0x01 or 0x00 byte. For example, -** if the requested column contains "a b X c d X X" and the position-list -** for 'X' is requested, the buffer returned may contain: -** -** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00 -** -** This function works regardless of whether or not the phrase is deferred, -** incremental, or neither. -*/ -int sqlite3Fts3EvalPhrasePoslist( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - Fts3Expr *pExpr, /* Phrase to return doclist for */ - int iCol, /* Column to return position list for */ - char **ppOut /* OUT: Pointer to position list */ -){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - char *pIter; - int iThis; - sqlite3_int64 iDocid; - - /* If this phrase is applies specifically to some column other than - ** column iCol, return a NULL pointer. */ - *ppOut = 0; - assert( iCol>=0 && iColnColumn ); - if( (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) ){ - return SQLITE_OK; - } - - iDocid = pExpr->iDocid; - pIter = pPhrase->doclist.pList; - if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ - int rc = SQLITE_OK; - int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ - int bOr = 0; - u8 bTreeEof = 0; - Fts3Expr *p; /* Used to iterate from pExpr to root */ - Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ - int bMatch; - - /* Check if this phrase descends from an OR expression node. If not, - ** return NULL. Otherwise, the entry that corresponds to docid - ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the - ** tree that the node is part of has been marked as EOF, but the node - ** itself is not EOF, then it may point to an earlier entry. */ - pNear = pExpr; - for(p=pExpr->pParent; p; p=p->pParent){ - if( p->eType==FTSQUERY_OR ) bOr = 1; - if( p->eType==FTSQUERY_NEAR ) pNear = p; - if( p->bEof ) bTreeEof = 1; - } - if( bOr==0 ) return SQLITE_OK; - - /* This is the descendent of an OR node. In this case we cannot use - ** an incremental phrase. Load the entire doclist for the phrase - ** into memory in this case. */ - if( pPhrase->bIncr ){ - int bEofSave = pNear->bEof; - fts3EvalRestart(pCsr, pNear, &rc); - while( rc==SQLITE_OK && !pNear->bEof ){ - fts3EvalNextRow(pCsr, pNear, &rc); - if( bEofSave==0 && pNear->iDocid==iDocid ) break; - } - assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); - } - if( bTreeEof ){ - while( rc==SQLITE_OK && !pNear->bEof ){ - fts3EvalNextRow(pCsr, pNear, &rc); - } - } - if( rc!=SQLITE_OK ) return rc; - - bMatch = 1; - for(p=pNear; p; p=p->pLeft){ - u8 bEof = 0; - Fts3Expr *pTest = p; - Fts3Phrase *pPh; - assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); - if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; - assert( pTest->eType==FTSQUERY_PHRASE ); - pPh = pTest->pPhrase; - - pIter = pPh->pOrPoslist; - iDocid = pPh->iOrDocid; - if( pCsr->bDesc==bDescDoclist ){ - bEof = !pPh->doclist.nAll || - (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &bEof - ); - } - }else{ - bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - int dummy; - sqlite3Fts3DoclistPrev( - bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); - } - } - pPh->pOrPoslist = pIter; - pPh->iOrDocid = iDocid; - if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; - } - - if( bMatch ){ - pIter = pPhrase->pOrPoslist; - }else{ - pIter = 0; - } - } - if( pIter==0 ) return SQLITE_OK; - - if( *pIter==0x01 ){ - pIter++; - pIter += fts3GetVarint32(pIter, &iThis); - }else{ - iThis = 0; - } - while( iThisdoclist, and -** * any Fts3MultiSegReader objects held by phrase tokens. -*/ -void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){ - if( pPhrase ){ - int i; - sqlite3_free(pPhrase->doclist.aAll); - fts3EvalInvalidatePoslist(pPhrase); - memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist)); - for(i=0; inToken; i++){ - fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr); - pPhrase->aToken[i].pSegcsr = 0; - } - } -} - - -/* -** Return SQLITE_CORRUPT_VTAB. -*/ -#ifdef SQLITE_DEBUG -int sqlite3Fts3Corrupt(){ - return SQLITE_CORRUPT_VTAB; -} -#endif - -#if !SQLITE_CORE -/* -** Initialize API pointer table, if required. -*/ -#ifdef _WIN32 -__declspec(dllexport) -#endif -int sqlite3_fts3_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3Fts3Init(db); -} -#endif - -#endif diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.h b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.h deleted file mode 100644 index c1aa8caf..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. -*/ -#include "sqlite3.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -int sqlite3Fts3Init(sqlite3 *db); - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3Int.h b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3Int.h deleted file mode 100644 index 9436e169..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3Int.h +++ /dev/null @@ -1,633 +0,0 @@ -/* -** 2009 Nov 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -*/ -#ifndef _FTSINT_H -#define _FTSINT_H - -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* FTS3/FTS4 require virtual tables */ -#ifdef SQLITE_OMIT_VIRTUALTABLE -# undef SQLITE_ENABLE_FTS3 -# undef SQLITE_ENABLE_FTS4 -#endif - -/* -** FTS4 is really an extension for FTS3. It is enabled using the -** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all -** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. -*/ -#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) -# define SQLITE_ENABLE_FTS3 -#endif - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* If not building as part of the core, include sqlite3ext.h. */ -#ifndef SQLITE_CORE -# include "sqlite3ext.h" -SQLITE_EXTENSION_INIT3 -#endif - -#include "sqlite3.h" -#include "fts3_tokenizer.h" -#include "fts3_hash.h" - -/* -** This constant determines the maximum depth of an FTS expression tree -** that the library will create and use. FTS uses recursion to perform -** various operations on the query tree, so the disadvantage of a large -** limit is that it may allow very large queries to use large amounts -** of stack space (perhaps causing a stack overflow). -*/ -#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH -# define SQLITE_FTS3_MAX_EXPR_DEPTH 12 -#endif - - -/* -** This constant controls how often segments are merged. Once there are -** FTS3_MERGE_COUNT segments of level N, they are merged into a single -** segment of level N+1. -*/ -#define FTS3_MERGE_COUNT 16 - -/* -** This is the maximum amount of data (in bytes) to store in the -** Fts3Table.pendingTerms hash table. Normally, the hash table is -** populated as documents are inserted/updated/deleted in a transaction -** and used to create a new segment when the transaction is committed. -** However if this limit is reached midway through a transaction, a new -** segment is created and the hash table cleared immediately. -*/ -#define FTS3_MAX_PENDING_DATA (1*1024*1024) - -/* -** Macro to return the number of elements in an array. SQLite has a -** similar macro called ArraySize(). Use a different name to avoid -** a collision when building an amalgamation with built-in FTS3. -*/ -#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0]))) - - -#ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif -#ifndef MAX -# define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -/* -** Maximum length of a varint encoded integer. The varint format is different -** from that used by SQLite, so the maximum length is 10, not 9. -*/ -#define FTS3_VARINT_MAX 10 - -#define FTS3_BUFFER_PADDING 8 - -/* -** FTS4 virtual tables may maintain multiple indexes - one index of all terms -** in the document set and zero or more prefix indexes. All indexes are stored -** as one or more b+-trees in the %_segments and %_segdir tables. -** -** It is possible to determine which index a b+-tree belongs to based on the -** value stored in the "%_segdir.level" column. Given this value L, the index -** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with -** level values between 0 and 1023 (inclusive) belong to index 0, all levels -** between 1024 and 2047 to index 1, and so on. -** -** It is considered impossible for an index to use more than 1024 levels. In -** theory though this may happen, but only after at least -** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables. -*/ -#define FTS3_SEGDIR_MAXLEVEL 1024 -#define FTS3_SEGDIR_MAXLEVEL_STR "1024" - -/* -** The testcase() macro is only used by the amalgamation. If undefined, -** make it a no-op. -*/ -#ifndef testcase -# define testcase(X) -#endif - -/* -** Terminator values for position-lists and column-lists. -*/ -#define POS_COLUMN (1) /* Column-list terminator */ -#define POS_END (0) /* Position-list terminator */ - -/* -** The assert_fts3_nc() macro is similar to the assert() macro, except that it -** is used for assert() conditions that are true only if it can be -** guranteed that the database is not corrupt. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) -extern int sqlite3_fts3_may_be_corrupt; -# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x)) -#else -# define assert_fts3_nc(x) assert(x) -#endif - -/* -** This section provides definitions to allow the -** FTS3 extension to be compiled outside of the -** amalgamation. -*/ -#ifndef SQLITE_AMALGAMATION -/* -** Macros indicating that conditional expressions are always true or -** false. -*/ -#ifdef SQLITE_COVERAGE_TEST -# define ALWAYS(x) (1) -# define NEVER(X) (0) -#elif defined(SQLITE_DEBUG) -# define ALWAYS(x) sqlite3Fts3Always((x)!=0) -# define NEVER(x) sqlite3Fts3Never((x)!=0) -int sqlite3Fts3Always(int b); -int sqlite3Fts3Never(int b); -#else -# define ALWAYS(x) (x) -# define NEVER(x) (x) -#endif - -/* -** Internal types used by SQLite. -*/ -typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ -typedef short int i16; /* 2-byte (or larger) signed integer */ -typedef unsigned int u32; /* 4-byte unsigned integer */ -typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */ -typedef sqlite3_int64 i64; /* 8-byte signed integer */ - -/* -** Macro used to suppress compiler warnings for unused parameters. -*/ -#define UNUSED_PARAMETER(x) (void)(x) - -/* -** Activate assert() only if SQLITE_TEST is enabled. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* -** The TESTONLY macro is used to enclose variable declarations or -** other bits of code that are needed to support the arguments -** within testcase() and assert() macros. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) -# define TESTONLY(X) X -#else -# define TESTONLY(X) -#endif - -#endif /* SQLITE_AMALGAMATION */ - -#ifdef SQLITE_DEBUG -int sqlite3Fts3Corrupt(void); -# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() -#else -# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB -#endif - -typedef struct Fts3Table Fts3Table; -typedef struct Fts3Cursor Fts3Cursor; -typedef struct Fts3Expr Fts3Expr; -typedef struct Fts3Phrase Fts3Phrase; -typedef struct Fts3PhraseToken Fts3PhraseToken; - -typedef struct Fts3Doclist Fts3Doclist; -typedef struct Fts3SegFilter Fts3SegFilter; -typedef struct Fts3DeferredToken Fts3DeferredToken; -typedef struct Fts3SegReader Fts3SegReader; -typedef struct Fts3MultiSegReader Fts3MultiSegReader; - -typedef struct MatchinfoBuffer MatchinfoBuffer; - -/* -** A connection to a fulltext index is an instance of the following -** structure. The xCreate and xConnect methods create an instance -** of this structure and xDestroy and xDisconnect free that instance. -** All other methods receive a pointer to the structure as one of their -** arguments. -*/ -struct Fts3Table { - sqlite3_vtab base; /* Base class used by SQLite core */ - sqlite3 *db; /* The database connection */ - const char *zDb; /* logical database name */ - const char *zName; /* virtual table name */ - int nColumn; /* number of named columns in virtual table */ - char **azColumn; /* column names. malloced */ - u8 *abNotindexed; /* True for 'notindexed' columns */ - sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ - char *zContentTbl; /* content=xxx option, or NULL */ - char *zLanguageid; /* languageid=xxx option, or NULL */ - int nAutoincrmerge; /* Value configured by 'automerge' */ - u32 nLeafAdd; /* Number of leaf blocks added this trans */ - - /* Precompiled statements used by the implementation. Each of these - ** statements is run and reset within a single virtual table API call. - */ - sqlite3_stmt *aStmt[40]; - sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */ - - char *zReadExprlist; - char *zWriteExprlist; - - int nNodeSize; /* Soft limit for node size */ - u8 bFts4; /* True for FTS4, false for FTS3 */ - u8 bHasStat; /* True if %_stat table exists (2==unknown) */ - u8 bHasDocsize; /* True if %_docsize table exists */ - u8 bDescIdx; /* True if doclists are in reverse order */ - u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ - int nPgsz; /* Page size for host database */ - char *zSegmentsTbl; /* Name of %_segments table */ - sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ - - /* - ** The following array of hash tables is used to buffer pending index - ** updates during transactions. All pending updates buffered at any one - ** time must share a common language-id (see the FTS4 langid= feature). - ** The current language id is stored in variable iPrevLangid. - ** - ** A single FTS4 table may have multiple full-text indexes. For each index - ** there is an entry in the aIndex[] array. Index 0 is an index of all the - ** terms that appear in the document set. Each subsequent index in aIndex[] - ** is an index of prefixes of a specific length. - ** - ** Variable nPendingData contains an estimate the memory consumed by the - ** pending data structures, including hash table overhead, but not including - ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash - ** tables are flushed to disk. Variable iPrevDocid is the docid of the most - ** recently inserted record. - */ - int nIndex; /* Size of aIndex[] */ - struct Fts3Index { - int nPrefix; /* Prefix length (0 for main terms index) */ - Fts3Hash hPending; /* Pending terms table for this index */ - } *aIndex; - int nMaxPendingData; /* Max pending data before flush to disk */ - int nPendingData; /* Current bytes of pending data */ - sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ - int iPrevLangid; /* Langid of recently inserted document */ - int bPrevDelete; /* True if last operation was a delete */ - -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - /* State variables used for validating that the transaction control - ** methods of the virtual table are called at appropriate times. These - ** values do not contribute to FTS functionality; they are used for - ** verifying the operation of the SQLite core. - */ - int inTransaction; /* True after xBegin but before xCommit/xRollback */ - int mxSavepoint; /* Largest valid xSavepoint integer */ -#endif - -#ifdef SQLITE_TEST - /* True to disable the incremental doclist optimization. This is controled - ** by special insert command 'test-no-incr-doclist'. */ - int bNoIncrDoclist; -#endif -}; - -/* -** When the core wants to read from the virtual table, it creates a -** virtual table cursor (an instance of the following structure) using -** the xOpen method. Cursors are destroyed using the xClose method. -*/ -struct Fts3Cursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - i16 eSearch; /* Search strategy (see below) */ - u8 isEof; /* True if at End Of Results */ - u8 isRequireSeek; /* True if must seek pStmt to %_content row */ - u8 bSeekStmt; /* True if pStmt is a seek */ - sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ - Fts3Expr *pExpr; /* Parsed MATCH query string */ - int iLangid; /* Language being queried for */ - int nPhrase; /* Number of matchable phrases in query */ - Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ - sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ - char *pNextId; /* Pointer into the body of aDoclist */ - char *aDoclist; /* List of docids for full-text queries */ - int nDoclist; /* Size of buffer at aDoclist */ - u8 bDesc; /* True to sort in descending order */ - int eEvalmode; /* An FTS3_EVAL_XX constant */ - int nRowAvg; /* Average size of database rows, in pages */ - sqlite3_int64 nDoc; /* Documents in table */ - i64 iMinDocid; /* Minimum docid to return */ - i64 iMaxDocid; /* Maximum docid to return */ - int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ - MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */ -}; - -#define FTS3_EVAL_FILTER 0 -#define FTS3_EVAL_NEXT 1 -#define FTS3_EVAL_MATCHINFO 2 - -/* -** The Fts3Cursor.eSearch member is always set to one of the following. -** Actualy, Fts3Cursor.eSearch can be greater than or equal to -** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index -** of the column to be searched. For example, in -** -** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); -** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; -** -** Because the LHS of the MATCH operator is 2nd column "b", -** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, -** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" -** indicating that all columns should be searched, -** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. -*/ -#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ -#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ -#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ - -/* -** The lower 16-bits of the sqlite3_index_info.idxNum value set by -** the xBestIndex() method contains the Fts3Cursor.eSearch value described -** above. The upper 16-bits contain a combination of the following -** bits, used to describe extra constraints on full-text searches. -*/ -#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */ -#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */ -#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */ - -struct Fts3Doclist { - char *aAll; /* Array containing doclist (or NULL) */ - int nAll; /* Size of a[] in bytes */ - char *pNextDocid; /* Pointer to next docid */ - - sqlite3_int64 iDocid; /* Current docid (if pList!=0) */ - int bFreeList; /* True if pList should be sqlite3_free()d */ - char *pList; /* Pointer to position list following iDocid */ - int nList; /* Length of position list */ -}; - -/* -** A "phrase" is a sequence of one or more tokens that must match in -** sequence. A single token is the base case and the most common case. -** For a sequence of tokens contained in double-quotes (i.e. "one two three") -** nToken will be the number of tokens in the string. -*/ -struct Fts3PhraseToken { - char *z; /* Text of the token */ - int n; /* Number of bytes in buffer z */ - int isPrefix; /* True if token ends with a "*" character */ - int bFirst; /* True if token must appear at position 0 */ - - /* Variables above this point are populated when the expression is - ** parsed (by code in fts3_expr.c). Below this point the variables are - ** used when evaluating the expression. */ - Fts3DeferredToken *pDeferred; /* Deferred token object for this token */ - Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */ -}; - -struct Fts3Phrase { - /* Cache of doclist for this phrase. */ - Fts3Doclist doclist; - int bIncr; /* True if doclist is loaded incrementally */ - int iDoclistToken; - - /* Used by sqlite3Fts3EvalPhrasePoslist() if this is a descendent of an - ** OR condition. */ - char *pOrPoslist; - i64 iOrDocid; - - /* Variables below this point are populated by fts3_expr.c when parsing - ** a MATCH expression. Everything above is part of the evaluation phase. - */ - int nToken; /* Number of tokens in the phrase */ - int iColumn; /* Index of column this phrase must match */ - Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */ -}; - -/* -** A tree of these objects forms the RHS of a MATCH operator. -** -** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist -** points to a malloced buffer, size nDoclist bytes, containing the results -** of this phrase query in FTS3 doclist format. As usual, the initial -** "Length" field found in doclists stored on disk is omitted from this -** buffer. -** -** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global -** matchinfo data. If it is not NULL, it points to an array of size nCol*3, -** where nCol is the number of columns in the queried FTS table. The array -** is populated as follows: -** -** aMI[iCol*3 + 0] = Undefined -** aMI[iCol*3 + 1] = Number of occurrences -** aMI[iCol*3 + 2] = Number of rows containing at least one instance -** -** The aMI array is allocated using sqlite3_malloc(). It should be freed -** when the expression node is. -*/ -struct Fts3Expr { - int eType; /* One of the FTSQUERY_XXX values defined below */ - int nNear; /* Valid if eType==FTSQUERY_NEAR */ - Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */ - Fts3Expr *pLeft; /* Left operand */ - Fts3Expr *pRight; /* Right operand */ - Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */ - - /* The following are used by the fts3_eval.c module. */ - sqlite3_int64 iDocid; /* Current docid */ - u8 bEof; /* True this expression is at EOF already */ - u8 bStart; /* True if iDocid is valid */ - u8 bDeferred; /* True if this expression is entirely deferred */ - - /* The following are used by the fts3_snippet.c module. */ - int iPhrase; /* Index of this phrase in matchinfo() results */ - u32 *aMI; /* See above */ -}; - -/* -** Candidate values for Fts3Query.eType. Note that the order of the first -** four values is in order of precedence when parsing expressions. For -** example, the following: -** -** "a OR b AND c NOT d NEAR e" -** -** is equivalent to: -** -** "a OR (b AND (c NOT (d NEAR e)))" -*/ -#define FTSQUERY_NEAR 1 -#define FTSQUERY_NOT 2 -#define FTSQUERY_AND 3 -#define FTSQUERY_OR 4 -#define FTSQUERY_PHRASE 5 - - -/* fts3_write.c */ -int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); -int sqlite3Fts3PendingTermsFlush(Fts3Table *); -void sqlite3Fts3PendingTermsClear(Fts3Table *); -int sqlite3Fts3Optimize(Fts3Table *); -int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, - sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); -int sqlite3Fts3SegReaderPending( - Fts3Table*,int,const char*,int,int,Fts3SegReader**); -void sqlite3Fts3SegReaderFree(Fts3SegReader *); -int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); -int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); - -int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); -int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); -int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); -int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); -void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); -int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); -#else -# define sqlite3Fts3FreeDeferredTokens(x) -# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK -# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK -# define sqlite3Fts3FreeDeferredDoclists(x) -# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK -#endif - -void sqlite3Fts3SegmentsClose(Fts3Table *); -int sqlite3Fts3MaxLevel(Fts3Table *, int *); - -/* Special values interpreted by sqlite3SegReaderCursor() */ -#define FTS3_SEGCURSOR_PENDING -1 -#define FTS3_SEGCURSOR_ALL -2 - -int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); -int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); -void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); - -int sqlite3Fts3SegReaderCursor(Fts3Table *, - int, int, int, const char *, int, int, int, Fts3MultiSegReader *); - -/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ -#define FTS3_SEGMENT_REQUIRE_POS 0x00000001 -#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 -#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 -#define FTS3_SEGMENT_PREFIX 0x00000008 -#define FTS3_SEGMENT_SCAN 0x00000010 -#define FTS3_SEGMENT_FIRST 0x00000020 - -/* Type passed as 4th argument to SegmentReaderIterate() */ -struct Fts3SegFilter { - const char *zTerm; - int nTerm; - int iCol; - int flags; -}; - -struct Fts3MultiSegReader { - /* Used internally by sqlite3Fts3SegReaderXXX() calls */ - Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */ - int nSegment; /* Size of apSegment array */ - int nAdvance; /* How many seg-readers to advance */ - Fts3SegFilter *pFilter; /* Pointer to filter object */ - char *aBuffer; /* Buffer to merge doclists in */ - int nBuffer; /* Allocated size of aBuffer[] in bytes */ - - int iColFilter; /* If >=0, filter for this column */ - int bRestart; - - /* Used by fts3.c only. */ - int nCost; /* Cost of running iterator */ - int bLookup; /* True if a lookup of a single entry. */ - - /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */ - char *zTerm; /* Pointer to term buffer */ - int nTerm; /* Size of zTerm in bytes */ - char *aDoclist; /* Pointer to doclist buffer */ - int nDoclist; /* Size of aDoclist[] in bytes */ -}; - -int sqlite3Fts3Incrmerge(Fts3Table*,int,int); - -#define fts3GetVarint32(p, piVal) ( \ - (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \ -) - -/* fts3.c */ -void sqlite3Fts3ErrMsg(char**,const char*,...); -int sqlite3Fts3PutVarint(char *, sqlite3_int64); -int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); -int sqlite3Fts3GetVarint32(const char *, int *); -int sqlite3Fts3VarintLen(sqlite3_uint64); -void sqlite3Fts3Dequote(char *); -void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); -int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); -int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); -void sqlite3Fts3CreateStatTable(int*, Fts3Table*); -int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc); - -/* fts3_tokenizer.c */ -const char *sqlite3Fts3NextToken(const char *, int *); -int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); -int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, - sqlite3_tokenizer **, char ** -); -int sqlite3Fts3IsIdChar(char); - -/* fts3_snippet.c */ -void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); -void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, - const char *, const char *, int, int -); -void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); -void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p); - -/* fts3_expr.c */ -int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, - char **, int, int, int, const char *, int, Fts3Expr **, char ** -); -void sqlite3Fts3ExprFree(Fts3Expr *); -#ifdef SQLITE_TEST -int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); -int sqlite3Fts3InitTerm(sqlite3 *db); -#endif - -int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, - sqlite3_tokenizer_cursor ** -); - -/* fts3_aux.c */ -int sqlite3Fts3InitAux(sqlite3 *db); - -void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); - -int sqlite3Fts3MsrIncrStart( - Fts3Table*, Fts3MultiSegReader*, int, const char*, int); -int sqlite3Fts3MsrIncrNext( - Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); -int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); -int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); -int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); - -/* fts3_tokenize_vtab.c */ -int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); - -/* fts3_unicode2.c (functions generated by parsing unicode text files) */ -#ifndef SQLITE_DISABLE_FTS3_UNICODE -int sqlite3FtsUnicodeFold(int, int); -int sqlite3FtsUnicodeIsalnum(int); -int sqlite3FtsUnicodeIsdiacritic(int); -#endif - -#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ -#endif /* _FTSINT_H */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_aux.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_aux.c deleted file mode 100644 index 08edc00f..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_aux.c +++ /dev/null @@ -1,551 +0,0 @@ -/* -** 2011 Jan 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include - -typedef struct Fts3auxTable Fts3auxTable; -typedef struct Fts3auxCursor Fts3auxCursor; - -struct Fts3auxTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - Fts3Table *pFts3Tab; -}; - -struct Fts3auxCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - Fts3MultiSegReader csr; /* Must be right after "base" */ - Fts3SegFilter filter; - char *zStop; - int nStop; /* Byte-length of string zStop */ - int iLangid; /* Language id to query */ - int isEof; /* True if cursor is at EOF */ - sqlite3_int64 iRowid; /* Current rowid */ - - int iCol; /* Current value of 'col' column */ - int nStat; /* Size of aStat[] array */ - struct Fts3auxColstats { - sqlite3_int64 nDoc; /* 'documents' values for current csr row */ - sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ - } *aStat; -}; - -/* -** Schema of the terms table. -*/ -#define FTS3_AUX_SCHEMA \ - "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)" - -/* -** This function does all the work for both the xConnect and xCreate methods. -** These tables have no persistent representation of their own, so xConnect -** and xCreate are identical operations. -*/ -static int fts3auxConnectMethod( - sqlite3 *db, /* Database connection */ - void *pUnused, /* Unused */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - char const *zDb; /* Name of database (e.g. "main") */ - char const *zFts3; /* Name of fts3 table */ - int nDb; /* Result of strlen(zDb) */ - int nFts3; /* Result of strlen(zFts3) */ - sqlite3_int64 nByte; /* Bytes of space to allocate here */ - int rc; /* value returned by declare_vtab() */ - Fts3auxTable *p; /* Virtual table object to return */ - - UNUSED_PARAMETER(pUnused); - - /* The user should invoke this in one of two forms: - ** - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table); - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table); - */ - if( argc!=4 && argc!=5 ) goto bad_args; - - zDb = argv[1]; - nDb = (int)strlen(zDb); - if( argc==5 ){ - if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){ - zDb = argv[3]; - nDb = (int)strlen(zDb); - zFts3 = argv[4]; - }else{ - goto bad_args; - } - }else{ - zFts3 = argv[3]; - } - nFts3 = (int)strlen(zFts3); - - rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA); - if( rc!=SQLITE_OK ) return rc; - - nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; - p = (Fts3auxTable *)sqlite3_malloc64(nByte); - if( !p ) return SQLITE_NOMEM; - memset(p, 0, nByte); - - p->pFts3Tab = (Fts3Table *)&p[1]; - p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1]; - p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1]; - p->pFts3Tab->db = db; - p->pFts3Tab->nIndex = 1; - - memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); - memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); - sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); - - *ppVtab = (sqlite3_vtab *)p; - return SQLITE_OK; - - bad_args: - sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor"); - return SQLITE_ERROR; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3auxTable *p = (Fts3auxTable *)pVtab; - Fts3Table *pFts3 = p->pFts3Tab; - int i; - - /* Free any prepared statements held */ - for(i=0; iaStmt); i++){ - sqlite3_finalize(pFts3->aStmt[i]); - } - sqlite3_free(pFts3->zSegmentsTbl); - sqlite3_free(p); - return SQLITE_OK; -} - -#define FTS4AUX_EQ_CONSTRAINT 1 -#define FTS4AUX_GE_CONSTRAINT 2 -#define FTS4AUX_LE_CONSTRAINT 4 - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3auxBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - int iEq = -1; - int iGe = -1; - int iLe = -1; - int iLangid = -1; - int iNext = 1; /* Next free argvIndex value */ - - UNUSED_PARAMETER(pVTab); - - /* This vtab delivers always results in "ORDER BY term ASC" order. */ - if( pInfo->nOrderBy==1 - && pInfo->aOrderBy[0].iColumn==0 - && pInfo->aOrderBy[0].desc==0 - ){ - pInfo->orderByConsumed = 1; - } - - /* Search for equality and range constraints on the "term" column. - ** And equality constraints on the hidden "languageid" column. */ - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable ){ - int op = pInfo->aConstraint[i].op; - int iCol = pInfo->aConstraint[i].iColumn; - - if( iCol==0 ){ - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; - if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; - } - if( iCol==4 ){ - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i; - } - } - } - - if( iEq>=0 ){ - pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; - pInfo->aConstraintUsage[iEq].argvIndex = iNext++; - pInfo->estimatedCost = 5; - }else{ - pInfo->idxNum = 0; - pInfo->estimatedCost = 20000; - if( iGe>=0 ){ - pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; - pInfo->aConstraintUsage[iGe].argvIndex = iNext++; - pInfo->estimatedCost /= 2; - } - if( iLe>=0 ){ - pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; - pInfo->aConstraintUsage[iLe].argvIndex = iNext++; - pInfo->estimatedCost /= 2; - } - } - if( iLangid>=0 ){ - pInfo->aConstraintUsage[iLangid].argvIndex = iNext++; - pInfo->estimatedCost--; - } - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3auxCursor *pCsr; /* Pointer to cursor object to return */ - - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor)); - if( !pCsr ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(Fts3auxCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - - sqlite3Fts3SegmentsClose(pFts3); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->zStop); - sqlite3_free(pCsr->aStat); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){ - if( nSize>pCsr->nStat ){ - struct Fts3auxColstats *aNew; - aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat, - sizeof(struct Fts3auxColstats) * nSize - ); - if( aNew==0 ) return SQLITE_NOMEM; - memset(&aNew[pCsr->nStat], 0, - sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat) - ); - pCsr->aStat = aNew; - pCsr->nStat = nSize; - } - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - - /* Increment our pretend rowid value. */ - pCsr->iRowid++; - - for(pCsr->iCol++; pCsr->iColnStat; pCsr->iCol++){ - if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK; - } - - rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr); - if( rc==SQLITE_ROW ){ - int i = 0; - int nDoclist = pCsr->csr.nDoclist; - char *aDoclist = pCsr->csr.aDoclist; - int iCol; - - int eState = 0; - - if( pCsr->zStop ){ - int n = (pCsr->nStopcsr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm; - int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n); - if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){ - pCsr->isEof = 1; - return SQLITE_OK; - } - } - - if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM; - memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat); - iCol = 0; - - while( iaStat[0].nDoc++; - eState = 1; - iCol = 0; - break; - - /* State 1. In this state we are expecting either a 1, indicating - ** that the following integer will be a column number, or the - ** start of a position list for column 0. - ** - ** The only difference between state 1 and state 2 is that if the - ** integer encountered in state 1 is not 0 or 1, then we need to - ** increment the column 0 "nDoc" count for this term. - */ - case 1: - assert( iCol==0 ); - if( v>1 ){ - pCsr->aStat[1].nDoc++; - } - eState = 2; - /* fall through */ - - case 2: - if( v==0 ){ /* 0x00. Next integer will be a docid. */ - eState = 0; - }else if( v==1 ){ /* 0x01. Next integer will be a column number. */ - eState = 3; - }else{ /* 2 or greater. A position. */ - pCsr->aStat[iCol+1].nOcc++; - pCsr->aStat[0].nOcc++; - } - break; - - /* State 3. The integer just read is a column number. */ - default: assert( eState==3 ); - iCol = (int)v; - if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM; - pCsr->aStat[iCol+1].nDoc++; - eState = 2; - break; - } - } - - pCsr->iCol = 0; - rc = SQLITE_OK; - }else{ - pCsr->isEof = 1; - } - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3auxFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - int isScan = 0; - int iLangVal = 0; /* Language id to query */ - - int iEq = -1; /* Index of term=? value in apVal */ - int iGe = -1; /* Index of term>=? value in apVal */ - int iLe = -1; /* Index of term<=? value in apVal */ - int iLangid = -1; /* Index of languageid=? value in apVal */ - int iNext = 0; - - UNUSED_PARAMETER(nVal); - UNUSED_PARAMETER(idxStr); - - assert( idxStr==0 ); - assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 - || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT - || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) - ); - - if( idxNum==FTS4AUX_EQ_CONSTRAINT ){ - iEq = iNext++; - }else{ - isScan = 1; - if( idxNum & FTS4AUX_GE_CONSTRAINT ){ - iGe = iNext++; - } - if( idxNum & FTS4AUX_LE_CONSTRAINT ){ - iLe = iNext++; - } - } - if( iNextfilter.zTerm); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->aStat); - memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); - - pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; - if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; - - if( iEq>=0 || iGe>=0 ){ - const unsigned char *zStr = sqlite3_value_text(apVal[0]); - assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) ); - if( zStr ){ - pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); - if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; - pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm); - } - } - - if( iLe>=0 ){ - pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe])); - if( pCsr->zStop==0 ) return SQLITE_NOMEM; - pCsr->nStop = (int)strlen(pCsr->zStop); - } - - if( iLangid>=0 ){ - iLangVal = sqlite3_value_int(apVal[iLangid]); - - /* If the user specified a negative value for the languageid, use zero - ** instead. This works, as the "languageid=?" constraint will also - ** be tested by the VDBE layer. The test will always be false (since - ** this module will not return a row with a negative languageid), and - ** so the overall query will return zero rows. */ - if( iLangVal<0 ) iLangVal = 0; - } - pCsr->iLangid = iLangVal; - - rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL, - pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); - } - - if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor); - return rc; -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - return pCsr->isEof; -} - -/* -** xColumn - Return a column value. -*/ -static int fts3auxColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3auxCursor *p = (Fts3auxCursor *)pCursor; - - assert( p->isEof==0 ); - switch( iCol ){ - case 0: /* term */ - sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); - break; - - case 1: /* col */ - if( p->iCol ){ - sqlite3_result_int(pCtx, p->iCol-1); - }else{ - sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC); - } - break; - - case 2: /* documents */ - sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc); - break; - - case 3: /* occurrences */ - sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc); - break; - - default: /* languageid */ - assert( iCol==4 ); - sqlite3_result_int(pCtx, p->iLangid); - break; - } - - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3auxRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - *pRowid = pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3aux module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -int sqlite3Fts3InitAux(sqlite3 *db){ - static const sqlite3_module fts3aux_module = { - 0, /* iVersion */ - fts3auxConnectMethod, /* xCreate */ - fts3auxConnectMethod, /* xConnect */ - fts3auxBestIndexMethod, /* xBestIndex */ - fts3auxDisconnectMethod, /* xDisconnect */ - fts3auxDisconnectMethod, /* xDestroy */ - fts3auxOpenMethod, /* xOpen */ - fts3auxCloseMethod, /* xClose */ - fts3auxFilterMethod, /* xFilter */ - fts3auxNextMethod, /* xNext */ - fts3auxEofMethod, /* xEof */ - fts3auxColumnMethod, /* xColumn */ - fts3auxRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0 /* xShadowName */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_expr.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_expr.c deleted file mode 100644 index 5775fbca..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_expr.c +++ /dev/null @@ -1,1291 +0,0 @@ -/* -** 2008 Nov 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This module contains code that implements a parser for fts3 query strings -** (the right-hand argument to the MATCH operator). Because the supported -** syntax is relatively simple, the whole tokenizer/parser system is -** hand-coded. -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* -** By default, this module parses the legacy syntax that has been -** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined, then it uses the new syntax. The differences between -** the new and the old syntaxes are: -** -** a) The new syntax supports parenthesis. The old does not. -** -** b) The new syntax supports the AND and NOT operators. The old does not. -** -** c) The old syntax supports the "-" token qualifier. This is not -** supported by the new syntax (it is replaced by the NOT operator). -** -** d) When using the old syntax, the OR operator has a greater precedence -** than an implicit AND. When using the new, both implicity and explicit -** AND operators have a higher precedence than OR. -** -** If compiled with SQLITE_TEST defined, then this module exports the -** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable -** to zero causes the module to use the old syntax. If it is set to -** non-zero the new syntax is activated. This is so both syntaxes can -** be tested using a single build of testfixture. -** -** The following describes the syntax supported by the fts3 MATCH -** operator in a similar format to that used by the lemon parser -** generator. This module does not use actually lemon, it uses a -** custom parser. -** -** query ::= andexpr (OR andexpr)*. -** -** andexpr ::= notexpr (AND? notexpr)*. -** -** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*. -** notexpr ::= LP query RP. -** -** nearexpr ::= phrase (NEAR distance_opt nearexpr)*. -** -** distance_opt ::= . -** distance_opt ::= / INTEGER. -** -** phrase ::= TOKEN. -** phrase ::= COLUMN:TOKEN. -** phrase ::= "TOKEN TOKEN TOKEN...". -*/ - -#ifdef SQLITE_TEST -int sqlite3_fts3_enable_parentheses = 0; -#else -# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS -# define sqlite3_fts3_enable_parentheses 1 -# else -# define sqlite3_fts3_enable_parentheses 0 -# endif -#endif - -/* -** Default span for NEAR operators. -*/ -#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10 - -#include -#include - -/* -** isNot: -** This variable is used by function getNextNode(). When getNextNode() is -** called, it sets ParseContext.isNot to true if the 'next node' is a -** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the -** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to -** zero. -*/ -typedef struct ParseContext ParseContext; -struct ParseContext { - sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ - int iLangid; /* Language id used with tokenizer */ - const char **azCol; /* Array of column names for fts3 table */ - int bFts4; /* True to allow FTS4-only syntax */ - int nCol; /* Number of entries in azCol[] */ - int iDefaultCol; /* Default column to query */ - int isNot; /* True if getNextNode() sees a unary - */ - sqlite3_context *pCtx; /* Write error message here */ - int nNest; /* Number of nested brackets */ -}; - -/* -** This function is equivalent to the standard isspace() function. -** -** The standard isspace() can be awkward to use safely, because although it -** is defined to accept an argument of type int, its behavior when passed -** an integer that falls outside of the range of the unsigned char type -** is undefined (and sometimes, "undefined" means segfault). This wrapper -** is defined to accept an argument of type char, and always returns 0 for -** any values that fall outside of the range of the unsigned char type (i.e. -** negative values). -*/ -static int fts3isspace(char c){ - return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; -} - -/* -** Allocate nByte bytes of memory using sqlite3_malloc(). If successful, -** zero the memory before returning a pointer to it. If unsuccessful, -** return NULL. -*/ -static void *fts3MallocZero(sqlite3_int64 nByte){ - void *pRet = sqlite3_malloc64(nByte); - if( pRet ) memset(pRet, 0, nByte); - return pRet; -} - -int sqlite3Fts3OpenTokenizer( - sqlite3_tokenizer *pTokenizer, - int iLangid, - const char *z, - int n, - sqlite3_tokenizer_cursor **ppCsr -){ - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr = 0; - int rc; - - rc = pModule->xOpen(pTokenizer, z, n, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( rc==SQLITE_OK ){ - pCsr->pTokenizer = pTokenizer; - if( pModule->iVersion>=1 ){ - rc = pModule->xLanguageid(pCsr, iLangid); - if( rc!=SQLITE_OK ){ - pModule->xClose(pCsr); - pCsr = 0; - } - } - } - *ppCsr = pCsr; - return rc; -} - -/* -** Function getNextNode(), which is called by fts3ExprParse(), may itself -** call fts3ExprParse(). So this forward declaration is required. -*/ -static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *); - -/* -** Extract the next token from buffer z (length n) using the tokenizer -** and other information (column names etc.) in pParse. Create an Fts3Expr -** structure of type FTSQUERY_PHRASE containing a phrase consisting of this -** single token and set *ppExpr to point to it. If the end of the buffer is -** reached before a token is found, set *ppExpr to zero. It is the -** responsibility of the caller to eventually deallocate the allocated -** Fts3Expr structure (if any) by passing it to sqlite3_free(). -** -** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation -** fails. -*/ -static int getNextToken( - ParseContext *pParse, /* fts3 query parse context */ - int iCol, /* Value for Fts3Phrase.iColumn */ - const char *z, int n, /* Input string */ - Fts3Expr **ppExpr, /* OUT: expression */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - sqlite3_tokenizer_cursor *pCursor; - Fts3Expr *pRet = 0; - int i = 0; - - /* Set variable i to the maximum number of bytes of input to tokenize. */ - for(i=0; iiLangid, z, i, &pCursor); - if( rc==SQLITE_OK ){ - const char *zToken; - int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; - sqlite3_int64 nByte; /* total space to allocate */ - - rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); - if( rc==SQLITE_OK ){ - nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; - pRet = (Fts3Expr *)fts3MallocZero(nByte); - if( !pRet ){ - rc = SQLITE_NOMEM; - }else{ - pRet->eType = FTSQUERY_PHRASE; - pRet->pPhrase = (Fts3Phrase *)&pRet[1]; - pRet->pPhrase->nToken = 1; - pRet->pPhrase->iColumn = iCol; - pRet->pPhrase->aToken[0].n = nToken; - pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1]; - memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken); - - if( iEndpPhrase->aToken[0].isPrefix = 1; - iEnd++; - } - - while( 1 ){ - if( !sqlite3_fts3_enable_parentheses - && iStart>0 && z[iStart-1]=='-' - ){ - pParse->isNot = 1; - iStart--; - }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){ - pRet->pPhrase->aToken[0].bFirst = 1; - iStart--; - }else{ - break; - } - } - - } - *pnConsumed = iEnd; - }else if( i && rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - - pModule->xClose(pCursor); - } - - *ppExpr = pRet; - return rc; -} - - -/* -** Enlarge a memory allocation. If an out-of-memory allocation occurs, -** then free the old allocation. -*/ -static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){ - void *pRet = sqlite3_realloc64(pOrig, nNew); - if( !pRet ){ - sqlite3_free(pOrig); - } - return pRet; -} - -/* -** Buffer zInput, length nInput, contains the contents of a quoted string -** that appeared as part of an fts3 query expression. Neither quote character -** is included in the buffer. This function attempts to tokenize the entire -** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE -** containing the results. -** -** If successful, SQLITE_OK is returned and *ppExpr set to point at the -** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory -** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set -** to 0. -*/ -static int getNextString( - ParseContext *pParse, /* fts3 query parse context */ - const char *zInput, int nInput, /* Input string */ - Fts3Expr **ppExpr /* OUT: expression */ -){ - sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - Fts3Expr *p = 0; - sqlite3_tokenizer_cursor *pCursor = 0; - char *zTemp = 0; - int nTemp = 0; - - const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase); - int nToken = 0; - - /* The final Fts3Expr data structure, including the Fts3Phrase, - ** Fts3PhraseToken structures token buffers are all stored as a single - ** allocation so that the expression can be freed with a single call to - ** sqlite3_free(). Setting this up requires a two pass approach. - ** - ** The first pass, in the block below, uses a tokenizer cursor to iterate - ** through the tokens in the expression. This pass uses fts3ReallocOrFree() - ** to assemble data in two dynamic buffers: - ** - ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase - ** structure, followed by the array of Fts3PhraseToken - ** structures. This pass only populates the Fts3PhraseToken array. - ** - ** Buffer zTemp: Contains copies of all tokens. - ** - ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, - ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase - ** structures. - */ - rc = sqlite3Fts3OpenTokenizer( - pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); - if( rc==SQLITE_OK ){ - int ii; - for(ii=0; rc==SQLITE_OK; ii++){ - const char *zByte; - int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0; - rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); - if( rc==SQLITE_OK ){ - Fts3PhraseToken *pToken; - - p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); - if( !p ) goto no_mem; - - zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte); - if( !zTemp ) goto no_mem; - - assert( nToken==ii ); - pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii]; - memset(pToken, 0, sizeof(Fts3PhraseToken)); - - memcpy(&zTemp[nTemp], zByte, nByte); - nTemp += nByte; - - pToken->n = nByte; - pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^'); - nToken = ii+1; - } - } - - pModule->xClose(pCursor); - pCursor = 0; - } - - if( rc==SQLITE_DONE ){ - int jj; - char *zBuf = 0; - - p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp); - if( !p ) goto no_mem; - memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p); - p->eType = FTSQUERY_PHRASE; - p->pPhrase = (Fts3Phrase *)&p[1]; - p->pPhrase->iColumn = pParse->iDefaultCol; - p->pPhrase->nToken = nToken; - - zBuf = (char *)&p->pPhrase->aToken[nToken]; - if( zTemp ){ - memcpy(zBuf, zTemp, nTemp); - sqlite3_free(zTemp); - }else{ - assert( nTemp==0 ); - } - - for(jj=0; jjpPhrase->nToken; jj++){ - p->pPhrase->aToken[jj].z = zBuf; - zBuf += p->pPhrase->aToken[jj].n; - } - rc = SQLITE_OK; - } - - *ppExpr = p; - return rc; -no_mem: - - if( pCursor ){ - pModule->xClose(pCursor); - } - sqlite3_free(zTemp); - sqlite3_free(p); - *ppExpr = 0; - return SQLITE_NOMEM; -} - -/* -** The output variable *ppExpr is populated with an allocated Fts3Expr -** structure, or set to 0 if the end of the input buffer is reached. -** -** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM -** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered. -** If SQLITE_ERROR is returned, pContext is populated with an error message. -*/ -static int getNextNode( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Input string */ - Fts3Expr **ppExpr, /* OUT: expression */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - static const struct Fts3Keyword { - char *z; /* Keyword text */ - unsigned char n; /* Length of the keyword */ - unsigned char parenOnly; /* Only valid in paren mode */ - unsigned char eType; /* Keyword code */ - } aKeyword[] = { - { "OR" , 2, 0, FTSQUERY_OR }, - { "AND", 3, 1, FTSQUERY_AND }, - { "NOT", 3, 1, FTSQUERY_NOT }, - { "NEAR", 4, 0, FTSQUERY_NEAR } - }; - int ii; - int iCol; - int iColLen; - int rc; - Fts3Expr *pRet = 0; - - const char *zInput = z; - int nInput = n; - - pParse->isNot = 0; - - /* Skip over any whitespace before checking for a keyword, an open or - ** close bracket, or a quoted string. - */ - while( nInput>0 && fts3isspace(*zInput) ){ - nInput--; - zInput++; - } - if( nInput==0 ){ - return SQLITE_DONE; - } - - /* See if we are dealing with a keyword. */ - for(ii=0; ii<(int)(sizeof(aKeyword)/sizeof(struct Fts3Keyword)); ii++){ - const struct Fts3Keyword *pKey = &aKeyword[ii]; - - if( (pKey->parenOnly & ~sqlite3_fts3_enable_parentheses)!=0 ){ - continue; - } - - if( nInput>=pKey->n && 0==memcmp(zInput, pKey->z, pKey->n) ){ - int nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM; - int nKey = pKey->n; - char cNext; - - /* If this is a "NEAR" keyword, check for an explicit nearness. */ - if( pKey->eType==FTSQUERY_NEAR ){ - assert( nKey==4 ); - if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){ - nNear = 0; - for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){ - nNear = nNear * 10 + (zInput[nKey] - '0'); - } - } - } - - /* At this point this is probably a keyword. But for that to be true, - ** the next byte must contain either whitespace, an open or close - ** parenthesis, a quote character, or EOF. - */ - cNext = zInput[nKey]; - if( fts3isspace(cNext) - || cNext=='"' || cNext=='(' || cNext==')' || cNext==0 - ){ - pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr)); - if( !pRet ){ - return SQLITE_NOMEM; - } - pRet->eType = pKey->eType; - pRet->nNear = nNear; - *ppExpr = pRet; - *pnConsumed = (int)((zInput - z) + nKey); - return SQLITE_OK; - } - - /* Turns out that wasn't a keyword after all. This happens if the - ** user has supplied a token such as "ORacle". Continue. - */ - } - } - - /* See if we are dealing with a quoted phrase. If this is the case, then - ** search for the closing quote and pass the whole string to getNextString() - ** for processing. This is easy to do, as fts3 has no syntax for escaping - ** a quote character embedded in a string. - */ - if( *zInput=='"' ){ - for(ii=1; iinNest++; - rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed); - *pnConsumed = (int)(zInput - z) + 1 + nConsumed; - return rc; - }else if( *zInput==')' ){ - pParse->nNest--; - *pnConsumed = (int)((zInput - z) + 1); - *ppExpr = 0; - return SQLITE_DONE; - } - } - - /* If control flows to this point, this must be a regular token, or - ** the end of the input. Read a regular token using the sqlite3_tokenizer - ** interface. Before doing so, figure out if there is an explicit - ** column specifier for the token. - ** - ** TODO: Strangely, it is not possible to associate a column specifier - ** with a quoted phrase, only with a single token. Not sure if this was - ** an implementation artifact or an intentional decision when fts3 was - ** first implemented. Whichever it was, this module duplicates the - ** limitation. - */ - iCol = pParse->iDefaultCol; - iColLen = 0; - for(ii=0; iinCol; ii++){ - const char *zStr = pParse->azCol[ii]; - int nStr = (int)strlen(zStr); - if( nInput>nStr && zInput[nStr]==':' - && sqlite3_strnicmp(zStr, zInput, nStr)==0 - ){ - iCol = ii; - iColLen = (int)((zInput - z) + nStr + 1); - break; - } - } - rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); - *pnConsumed += iColLen; - return rc; -} - -/* -** The argument is an Fts3Expr structure for a binary operator (any type -** except an FTSQUERY_PHRASE). Return an integer value representing the -** precedence of the operator. Lower values have a higher precedence (i.e. -** group more tightly). For example, in the C language, the == operator -** groups more tightly than ||, and would therefore have a higher precedence. -** -** When using the new fts3 query syntax (when SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined), the order of the operators in precedence from highest to -** lowest is: -** -** NEAR -** NOT -** AND (including implicit ANDs) -** OR -** -** Note that when using the old query syntax, the OR operator has a higher -** precedence than the AND operator. -*/ -static int opPrecedence(Fts3Expr *p){ - assert( p->eType!=FTSQUERY_PHRASE ); - if( sqlite3_fts3_enable_parentheses ){ - return p->eType; - }else if( p->eType==FTSQUERY_NEAR ){ - return 1; - }else if( p->eType==FTSQUERY_OR ){ - return 2; - } - assert( p->eType==FTSQUERY_AND ); - return 3; -} - -/* -** Argument ppHead contains a pointer to the current head of a query -** expression tree being parsed. pPrev is the expression node most recently -** inserted into the tree. This function adds pNew, which is always a binary -** operator node, into the expression tree based on the relative precedence -** of pNew and the existing nodes of the tree. This may result in the head -** of the tree changing, in which case *ppHead is set to the new root node. -*/ -static void insertBinaryOperator( - Fts3Expr **ppHead, /* Pointer to the root node of a tree */ - Fts3Expr *pPrev, /* Node most recently inserted into the tree */ - Fts3Expr *pNew /* New binary node to insert into expression tree */ -){ - Fts3Expr *pSplit = pPrev; - while( pSplit->pParent && opPrecedence(pSplit->pParent)<=opPrecedence(pNew) ){ - pSplit = pSplit->pParent; - } - - if( pSplit->pParent ){ - assert( pSplit->pParent->pRight==pSplit ); - pSplit->pParent->pRight = pNew; - pNew->pParent = pSplit->pParent; - }else{ - *ppHead = pNew; - } - pNew->pLeft = pSplit; - pSplit->pParent = pNew; -} - -/* -** Parse the fts3 query expression found in buffer z, length n. This function -** returns either when the end of the buffer is reached or an unmatched -** closing bracket - ')' - is encountered. -** -** If successful, SQLITE_OK is returned, *ppExpr is set to point to the -** parsed form of the expression and *pnConsumed is set to the number of -** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM -** (out of memory error) or SQLITE_ERROR (parse error) is returned. -*/ -static int fts3ExprParse( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - Fts3Expr *pRet = 0; - Fts3Expr *pPrev = 0; - Fts3Expr *pNotBranch = 0; /* Only used in legacy parse mode */ - int nIn = n; - const char *zIn = z; - int rc = SQLITE_OK; - int isRequirePhrase = 1; - - while( rc==SQLITE_OK ){ - Fts3Expr *p = 0; - int nByte = 0; - - rc = getNextNode(pParse, zIn, nIn, &p, &nByte); - assert( nByte>0 || (rc!=SQLITE_OK && p==0) ); - if( rc==SQLITE_OK ){ - if( p ){ - int isPhrase; - - if( !sqlite3_fts3_enable_parentheses - && p->eType==FTSQUERY_PHRASE && pParse->isNot - ){ - /* Create an implicit NOT operator. */ - Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr)); - if( !pNot ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pNot->eType = FTSQUERY_NOT; - pNot->pRight = p; - p->pParent = pNot; - if( pNotBranch ){ - pNot->pLeft = pNotBranch; - pNotBranch->pParent = pNot; - } - pNotBranch = pNot; - p = pPrev; - }else{ - int eType = p->eType; - isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); - - /* The isRequirePhrase variable is set to true if a phrase or - ** an expression contained in parenthesis is required. If a - ** binary operator (AND, OR, NOT or NEAR) is encounted when - ** isRequirePhrase is set, this is a syntax error. - */ - if( !isPhrase && isRequirePhrase ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase && !isRequirePhrase ){ - /* Insert an implicit AND operator. */ - Fts3Expr *pAnd; - assert( pRet && pPrev ); - pAnd = fts3MallocZero(sizeof(Fts3Expr)); - if( !pAnd ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pAnd->eType = FTSQUERY_AND; - insertBinaryOperator(&pRet, pPrev, pAnd); - pPrev = pAnd; - } - - /* This test catches attempts to make either operand of a NEAR - ** operator something other than a phrase. For example, either of - ** the following: - ** - ** (bracketed expression) NEAR phrase - ** phrase NEAR (bracketed expression) - ** - ** Return an error in either case. - */ - if( pPrev && ( - (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE) - || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR) - )){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase ){ - if( pRet ){ - assert( pPrev && pPrev->pLeft && pPrev->pRight==0 ); - pPrev->pRight = p; - p->pParent = pPrev; - }else{ - pRet = p; - } - }else{ - insertBinaryOperator(&pRet, pPrev, p); - } - isRequirePhrase = !isPhrase; - } - pPrev = p; - } - assert( nByte>0 ); - } - assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) ); - nIn -= nByte; - zIn += nByte; - } - - if( rc==SQLITE_DONE && pRet && isRequirePhrase ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - if( !sqlite3_fts3_enable_parentheses && pNotBranch ){ - if( !pRet ){ - rc = SQLITE_ERROR; - }else{ - Fts3Expr *pIter = pNotBranch; - while( pIter->pLeft ){ - pIter = pIter->pLeft; - } - pIter->pLeft = pRet; - pRet->pParent = pIter; - pRet = pNotBranch; - } - } - } - *pnConsumed = n - nIn; - -exprparse_out: - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRet); - sqlite3Fts3ExprFree(pNotBranch); - pRet = 0; - } - *ppExpr = pRet; - return rc; -} - -/* -** Return SQLITE_ERROR if the maximum depth of the expression tree passed -** as the only argument is more than nMaxDepth. -*/ -static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){ - int rc = SQLITE_OK; - if( p ){ - if( nMaxDepth<0 ){ - rc = SQLITE_TOOBIG; - }else{ - rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1); - } - } - } - return rc; -} - -/* -** This function attempts to transform the expression tree at (*pp) to -** an equivalent but more balanced form. The tree is modified in place. -** If successful, SQLITE_OK is returned and (*pp) set to point to the -** new root expression node. -** -** nMaxDepth is the maximum allowable depth of the balanced sub-tree. -** -** Otherwise, if an error occurs, an SQLite error code is returned and -** expression (*pp) freed. -*/ -static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ - int rc = SQLITE_OK; /* Return code */ - Fts3Expr *pRoot = *pp; /* Initial root node */ - Fts3Expr *pFree = 0; /* List of free nodes. Linked by pParent. */ - int eType = pRoot->eType; /* Type of node in this tree */ - - if( nMaxDepth==0 ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_OK ){ - if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ - Fts3Expr **apLeaf; - apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth); - if( 0==apLeaf ){ - rc = SQLITE_NOMEM; - }else{ - memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); - } - - if( rc==SQLITE_OK ){ - int i; - Fts3Expr *p; - - /* Set $p to point to the left-most leaf in the tree of eType nodes. */ - for(p=pRoot; p->eType==eType; p=p->pLeft){ - assert( p->pParent==0 || p->pParent->pLeft==p ); - assert( p->pLeft && p->pRight ); - } - - /* This loop runs once for each leaf in the tree of eType nodes. */ - while( 1 ){ - int iLvl; - Fts3Expr *pParent = p->pParent; /* Current parent of p */ - - assert( pParent==0 || pParent->pLeft==p ); - p->pParent = 0; - if( pParent ){ - pParent->pLeft = 0; - }else{ - pRoot = 0; - } - rc = fts3ExprBalance(&p, nMaxDepth-1); - if( rc!=SQLITE_OK ) break; - - for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; - pFree->pRight = p; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - apLeaf[iLvl] = 0; - } - } - if( p ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_TOOBIG; - break; - } - - /* If that was the last leaf node, break out of the loop */ - if( pParent==0 ) break; - - /* Set $p to point to the next leaf in the tree of eType nodes */ - for(p=pParent->pRight; p->eType==eType; p=p->pLeft); - - /* Remove pParent from the original tree. */ - assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); - pParent->pRight->pParent = pParent->pParent; - if( pParent->pParent ){ - pParent->pParent->pLeft = pParent->pRight; - }else{ - assert( pParent==pRoot ); - pRoot = pParent->pRight; - } - - /* Link pParent into the free node list. It will be used as an - ** internal node of the new tree. */ - pParent->pParent = pFree; - pFree = pParent; - } - - if( rc==SQLITE_OK ){ - p = 0; - for(i=0; ipParent = 0; - }else{ - assert( pFree!=0 ); - pFree->pRight = p; - pFree->pLeft = apLeaf[i]; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - } - } - } - pRoot = p; - }else{ - /* An error occurred. Delete the contents of the apLeaf[] array - ** and pFree list. Everything else is cleaned up by the call to - ** sqlite3Fts3ExprFree(pRoot) below. */ - Fts3Expr *pDel; - for(i=0; ipParent; - sqlite3_free(pDel); - } - } - - assert( pFree==0 ); - sqlite3_free( apLeaf ); - } - }else if( eType==FTSQUERY_NOT ){ - Fts3Expr *pLeft = pRoot->pLeft; - Fts3Expr *pRight = pRoot->pRight; - - pRoot->pLeft = 0; - pRoot->pRight = 0; - pLeft->pParent = 0; - pRight->pParent = 0; - - rc = fts3ExprBalance(&pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprBalance(&pRight, nMaxDepth-1); - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRight); - sqlite3Fts3ExprFree(pLeft); - }else{ - assert( pLeft && pRight ); - pRoot->pLeft = pLeft; - pLeft->pParent = pRoot; - pRoot->pRight = pRight; - pRight->pParent = pRoot; - } - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRoot); - pRoot = 0; - } - *pp = pRoot; - return rc; -} - -/* -** This function is similar to sqlite3Fts3ExprParse(), with the following -** differences: -** -** 1. It does not do expression rebalancing. -** 2. It does not check that the expression does not exceed the -** maximum allowable depth. -** 3. Even if it fails, *ppExpr may still be set to point to an -** expression tree. It should be deleted using sqlite3Fts3ExprFree() -** in this case. -*/ -static int fts3ExprParseUnbalanced( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr /* OUT: Parsed query structure */ -){ - int nParsed; - int rc; - ParseContext sParse; - - memset(&sParse, 0, sizeof(ParseContext)); - sParse.pTokenizer = pTokenizer; - sParse.iLangid = iLangid; - sParse.azCol = (const char **)azCol; - sParse.nCol = nCol; - sParse.iDefaultCol = iDefaultCol; - sParse.bFts4 = bFts4; - if( z==0 ){ - *ppExpr = 0; - return SQLITE_OK; - } - if( n<0 ){ - n = (int)strlen(z); - } - rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); - assert( rc==SQLITE_OK || *ppExpr==0 ); - - /* Check for mismatched parenthesis */ - if( rc==SQLITE_OK && sParse.nNest ){ - rc = SQLITE_ERROR; - } - - return rc; -} - -/* -** Parameters z and n contain a pointer to and length of a buffer containing -** an fts3 query expression, respectively. This function attempts to parse the -** query expression and create a tree of Fts3Expr structures representing the -** parsed expression. If successful, *ppExpr is set to point to the head -** of the parsed expression tree and SQLITE_OK is returned. If an error -** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse -** error) is returned and *ppExpr is set to 0. -** -** If parameter n is a negative number, then z is assumed to point to a -** nul-terminated string and the length is determined using strlen(). -** -** The first parameter, pTokenizer, is passed the fts3 tokenizer module to -** use to normalize query tokens while parsing the expression. The azCol[] -** array, which is assumed to contain nCol entries, should contain the names -** of each column in the target fts3 table, in order from left to right. -** Column names must be nul-terminated strings. -** -** The iDefaultCol parameter should be passed the index of the table column -** that appears on the left-hand-side of the MATCH operator (the default -** column to match against for tokens for which a column name is not explicitly -** specified as part of the query string), or -1 if tokens may by default -** match any table column. -*/ -int sqlite3Fts3ExprParse( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - char **pzErr /* OUT: Error message (sqlite3_malloc) */ -){ - int rc = fts3ExprParseUnbalanced( - pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr - ); - - /* Rebalance the expression. And check that its depth does not exceed - ** SQLITE_FTS3_MAX_EXPR_DEPTH. */ - if( rc==SQLITE_OK && *ppExpr ){ - rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(*ppExpr); - *ppExpr = 0; - if( rc==SQLITE_TOOBIG ){ - sqlite3Fts3ErrMsg(pzErr, - "FTS expression tree is too large (maximum depth %d)", - SQLITE_FTS3_MAX_EXPR_DEPTH - ); - rc = SQLITE_ERROR; - }else if( rc==SQLITE_ERROR ){ - sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z); - } - } - - return rc; -} - -/* -** Free a single node of an expression tree. -*/ -static void fts3FreeExprNode(Fts3Expr *p){ - assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); - sqlite3Fts3EvalPhraseCleanup(p->pPhrase); - sqlite3_free(p->aMI); - sqlite3_free(p); -} - -/* -** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse(). -** -** This function would be simpler if it recursively called itself. But -** that would mean passing a sufficiently large expression to ExprParse() -** could cause a stack overflow. -*/ -void sqlite3Fts3ExprFree(Fts3Expr *pDel){ - Fts3Expr *p; - assert( pDel==0 || pDel->pParent==0 ); - for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){ - assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft ); - } - while( p ){ - Fts3Expr *pParent = p->pParent; - fts3FreeExprNode(p); - if( pParent && p==pParent->pLeft && pParent->pRight ){ - p = pParent->pRight; - while( p && (p->pLeft || p->pRight) ){ - assert( p==p->pParent->pRight || p==p->pParent->pLeft ); - p = (p->pLeft ? p->pLeft : p->pRight); - } - }else{ - p = pParent; - } - } -} - -/**************************************************************************** -***************************************************************************** -** Everything after this point is just test code. -*/ - -#ifdef SQLITE_TEST - -#include - -/* -** Return a pointer to a buffer containing a text representation of the -** expression passed as the first argument. The buffer is obtained from -** sqlite3_malloc(). It is the responsibility of the caller to use -** sqlite3_free() to release the memory. If an OOM condition is encountered, -** NULL is returned. -** -** If the second argument is not NULL, then its contents are prepended to -** the returned expression text and then freed using sqlite3_free(). -*/ -static char *exprToString(Fts3Expr *pExpr, char *zBuf){ - if( pExpr==0 ){ - return sqlite3_mprintf(""); - } - switch( pExpr->eType ){ - case FTSQUERY_PHRASE: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - zBuf = sqlite3_mprintf( - "%zPHRASE %d 0", zBuf, pPhrase->iColumn); - for(i=0; zBuf && inToken; i++){ - zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, - pPhrase->aToken[i].n, pPhrase->aToken[i].z, - (pPhrase->aToken[i].isPrefix?"+":"") - ); - } - return zBuf; - } - - case FTSQUERY_NEAR: - zBuf = sqlite3_mprintf("%zNEAR/%d ", zBuf, pExpr->nNear); - break; - case FTSQUERY_NOT: - zBuf = sqlite3_mprintf("%zNOT ", zBuf); - break; - case FTSQUERY_AND: - zBuf = sqlite3_mprintf("%zAND ", zBuf); - break; - case FTSQUERY_OR: - zBuf = sqlite3_mprintf("%zOR ", zBuf); - break; - } - - if( zBuf ) zBuf = sqlite3_mprintf("%z{", zBuf); - if( zBuf ) zBuf = exprToString(pExpr->pLeft, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z} {", zBuf); - - if( zBuf ) zBuf = exprToString(pExpr->pRight, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z}", zBuf); - - return zBuf; -} - -/* -** This is the implementation of a scalar SQL function used to test the -** expression parser. It should be called as follows: -** -** fts3_exprtest(, , , ...); -** -** The first argument, , is the name of the fts3 tokenizer used -** to parse the query expression (see README.tokenizers). The second argument -** is the query expression to parse. Each subsequent argument is the name -** of a column of the fts3 table that the query expression may refer to. -** For example: -** -** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); -*/ -static void fts3ExprTestCommon( - int bRebalance, - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3_tokenizer *pTokenizer = 0; - int rc; - char **azCol = 0; - const char *zExpr; - int nExpr; - int nCol; - int ii; - Fts3Expr *pExpr; - char *zBuf = 0; - Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); - const char *zTokenizer = 0; - char *zErr = 0; - - if( argc<3 ){ - sqlite3_result_error(context, - "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1 - ); - return; - } - - zTokenizer = (const char*)sqlite3_value_text(argv[0]); - rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_error(context, zErr, -1); - } - sqlite3_free(zErr); - return; - } - - zExpr = (const char *)sqlite3_value_text(argv[1]); - nExpr = sqlite3_value_bytes(argv[1]); - nCol = argc-2; - azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *)); - if( !azCol ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - for(ii=0; iipModule->xDestroy(pTokenizer); - } - sqlite3_free(azCol); -} - -static void fts3ExprTest( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(0, context, argc, argv); -} -static void fts3ExprTestRebalance( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - fts3ExprTestCommon(1, context, argc, argv); -} - -/* -** Register the query expression parser test function fts3_exprtest() -** with database connection db. -*/ -int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ - int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 - ); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 - ); - } - return rc; -} - -#endif -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.c deleted file mode 100644 index 63e55b3d..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.c +++ /dev/null @@ -1,383 +0,0 @@ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of generic hash-tables used in SQLite. -** We've modified it slightly to serve as a standalone hash table -** implementation for the full-text indexing module. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include -#include - -#include "fts3_hash.h" - -/* -** Malloc and Free functions -*/ -static void *fts3HashMalloc(sqlite3_int64 n){ - void *p = sqlite3_malloc64(n); - if( p ){ - memset(p, 0, n); - } - return p; -} -static void fts3HashFree(void *p){ - sqlite3_free(p); -} - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "pNew" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants -** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass -** determines what kind of key the hash table will use. "copyKey" is -** true if the hash table should make its own private copy of keys and -** false if it should just use the supplied pointer. -*/ -void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ - assert( pNew!=0 ); - assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); - pNew->keyClass = keyClass; - pNew->copyKey = copyKey; - pNew->first = 0; - pNew->count = 0; - pNew->htsize = 0; - pNew->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -void sqlite3Fts3HashClear(Fts3Hash *pH){ - Fts3HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - fts3HashFree(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - Fts3HashElem *next_elem = elem->next; - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_STRING -*/ -static int fts3StrHash(const void *pKey, int nKey){ - const char *z = (const char *)pKey; - unsigned h = 0; - if( nKey<=0 ) nKey = (int) strlen(z); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ *z++; - nKey--; - } - return (int)(h & 0x7fffffff); -} -static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return strncmp((const char*)pKey1,(const char*)pKey2,n1); -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_BINARY -*/ -static int fts3BinHash(const void *pKey, int nKey){ - int h = 0; - const char *z = (const char *)pKey; - while( nKey-- > 0 ){ - h = (h<<3) ^ h ^ *(z++); - } - return h & 0x7fffffff; -} -static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return memcmp(pKey1,pKey2,n1); -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** The C syntax in this function definition may be unfamilar to some -** programmers, so we provide the following additional explanation: -** -** The name of the function is "ftsHashFunction". The function takes a -** single parameter "keyClass". The return value of ftsHashFunction() -** is a pointer to another function. Specifically, the return value -** of ftsHashFunction() is a pointer to a function that takes two parameters -** with types "const void*" and "int" and returns an "int". -*/ -static int (*ftsHashFunction(int keyClass))(const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrHash; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinHash; - } -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** For help in interpreted the obscure C code in the function definition, -** see the header comment on the previous function. -*/ -static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrCompare; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinCompare; - } -} - -/* Link an element into the hash table -*/ -static void fts3HashInsertElement( - Fts3Hash *pH, /* The complete hash table */ - struct _fts3ht *pEntry, /* The entry into which pNew is inserted */ - Fts3HashElem *pNew /* The element to be inserted */ -){ - Fts3HashElem *pHead; /* First element already in pEntry */ - pHead = pEntry->chain; - if( pHead ){ - pNew->next = pHead; - pNew->prev = pHead->prev; - if( pHead->prev ){ pHead->prev->next = pNew; } - else { pH->first = pNew; } - pHead->prev = pNew; - }else{ - pNew->next = pH->first; - if( pH->first ){ pH->first->prev = pNew; } - pNew->prev = 0; - pH->first = pNew; - } - pEntry->count++; - pEntry->chain = pNew; -} - - -/* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqliteMalloc() fails. -** -** Return non-zero if a memory allocation error occurs. -*/ -static int fts3Rehash(Fts3Hash *pH, int new_size){ - struct _fts3ht *new_ht; /* The new hash table */ - Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); - if( new_ht==0 ) return 1; - fts3HashFree(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size; - xHash = ftsHashFunction(pH->keyClass); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); - next_elem = elem->next; - fts3HashInsertElement(pH, &new_ht[h], elem); - } - return 0; -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. -*/ -static Fts3HashElem *fts3FindElementByHash( - const Fts3Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ -){ - Fts3HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ - int (*xCompare)(const void*,int,const void*,int); /* comparison function */ - - if( pH->ht ){ - struct _fts3ht *pEntry = &pH->ht[h]; - elem = pEntry->chain; - count = pEntry->count; - xCompare = ftsCompareFunction(pH->keyClass); - while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } - } - return 0; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void fts3RemoveElementByHash( - Fts3Hash *pH, /* The pH containing "elem" */ - Fts3HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ -){ - struct _fts3ht *pEntry; - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - pEntry = &pH->ht[h]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - pEntry->count--; - if( pEntry->count<=0 ){ - pEntry->chain = 0; - } - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree( elem ); - pH->count--; - if( pH->count<=0 ){ - assert( pH->first==0 ); - assert( pH->count==0 ); - fts3HashClear(pH); - } -} - -Fts3HashElem *sqlite3Fts3HashFindElem( - const Fts3Hash *pH, - const void *pKey, - int nKey -){ - int h; /* A hash on key */ - int (*xHash)(const void*,int); /* The hash function */ - - if( pH==0 || pH->ht==0 ) return 0; - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); -} - -/* -** Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){ - Fts3HashElem *pElem; /* The element that matches key (if any) */ - - pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey); - return pElem ? pElem->data : 0; -} - -/* Insert an element into the hash table pH. The key is pKey,nKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -void *sqlite3Fts3HashInsert( - Fts3Hash *pH, /* The hash table to insert into */ - const void *pKey, /* The key */ - int nKey, /* Number of bytes in the key */ - void *data /* The data */ -){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ - Fts3HashElem *elem; /* Used to loop thru the element list */ - Fts3HashElem *new_elem; /* New element added to the pH */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( pH!=0 ); - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = fts3FindElementByHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - fts3RemoveElementByHash(pH,elem,h); - }else{ - elem->data = data; - } - return old_data; - } - if( data==0 ) return 0; - if( (pH->htsize==0 && fts3Rehash(pH,8)) - || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2)) - ){ - pH->count = 0; - return data; - } - assert( pH->htsize>0 ); - new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); - if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = fts3HashMalloc( nKey ); - if( new_elem->pKey==0 ){ - fts3HashFree(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } - new_elem->nKey = nKey; - pH->count++; - assert( pH->htsize>0 ); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - fts3HashInsertElement(pH, &pH->ht[h], new_elem); - new_elem->data = data; - return 0; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.h b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.h deleted file mode 100644 index dc3fcf83..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_hash.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the header file for the generic hash-table implementation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct Fts3Hash Fts3Hash; -typedef struct Fts3HashElem Fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct Fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - Fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - Fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct Fts3HashElem { - Fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey); -void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); -void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); -void sqlite3Fts3HashClear(Fts3Hash*); -Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear -#define fts3HashFindElem sqlite3Fts3HashFindElem - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** Fts3Hash h; -** Fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_icu.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_icu.c deleted file mode 100644 index 0848a5aa..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_icu.c +++ /dev/null @@ -1,262 +0,0 @@ -/* -** 2007 June 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements a tokenizer for fts3 based on the ICU library. -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) -#ifdef SQLITE_ENABLE_ICU - -#include -#include -#include "fts3_tokenizer.h" - -#include -#include -#include -#include - -typedef struct IcuTokenizer IcuTokenizer; -typedef struct IcuCursor IcuCursor; - -struct IcuTokenizer { - sqlite3_tokenizer base; - char *zLocale; -}; - -struct IcuCursor { - sqlite3_tokenizer_cursor base; - - UBreakIterator *pIter; /* ICU break-iterator object */ - int nChar; /* Number of UChar elements in pInput */ - UChar *aChar; /* Copy of input using utf-16 encoding */ - int *aOffset; /* Offsets of each character in utf-8 input */ - - int nBuffer; - char *zBuffer; - - int iToken; -}; - -/* -** Create a new tokenizer instance. -*/ -static int icuCreate( - int argc, /* Number of entries in argv[] */ - const char * const *argv, /* Tokenizer creation arguments */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ -){ - IcuTokenizer *p; - int n = 0; - - if( argc>0 ){ - n = strlen(argv[0])+1; - } - p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n); - if( !p ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(IcuTokenizer)); - - if( n ){ - p->zLocale = (char *)&p[1]; - memcpy(p->zLocale, argv[0], n); - } - - *ppTokenizer = (sqlite3_tokenizer *)p; - - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int icuDestroy(sqlite3_tokenizer *pTokenizer){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int icuOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, /* Input string */ - int nInput, /* Length of zInput in bytes */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - IcuCursor *pCsr; - - const int32_t opt = U_FOLD_CASE_DEFAULT; - UErrorCode status = U_ZERO_ERROR; - int nChar; - - UChar32 c; - int iInput = 0; - int iOut = 0; - - *ppCursor = 0; - - if( zInput==0 ){ - nInput = 0; - zInput = ""; - }else if( nInput<0 ){ - nInput = strlen(zInput); - } - nChar = nInput+1; - pCsr = (IcuCursor *)sqlite3_malloc64( - sizeof(IcuCursor) + /* IcuCursor */ - ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ - (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ - ); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(IcuCursor)); - pCsr->aChar = (UChar *)&pCsr[1]; - pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; - - pCsr->aOffset[iOut] = iInput; - U8_NEXT(zInput, iInput, nInput, c); - while( c>0 ){ - int isError = 0; - c = u_foldCase(c, opt); - U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); - if( isError ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->aOffset[iOut] = iInput; - - if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); - if( !U_SUCCESS(status) ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->nChar = iOut; - - ubrk_first(pCsr->pIter); - *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to icuOpen(). -*/ -static int icuClose(sqlite3_tokenizer_cursor *pCursor){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - ubrk_close(pCsr->pIter); - sqlite3_free(pCsr->zBuffer); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. -*/ -static int icuNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - - int iStart = 0; - int iEnd = 0; - int nByte = 0; - - while( iStart==iEnd ){ - UChar32 c; - - iStart = ubrk_current(pCsr->pIter); - iEnd = ubrk_next(pCsr->pIter); - if( iEnd==UBRK_DONE ){ - return SQLITE_DONE; - } - - while( iStartaChar, iWhite, pCsr->nChar, c); - if( u_isspace(c) ){ - iStart = iWhite; - }else{ - break; - } - } - assert(iStart<=iEnd); - } - - do { - UErrorCode status = U_ZERO_ERROR; - if( nByte ){ - char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); - if( !zNew ){ - return SQLITE_NOMEM; - } - pCsr->zBuffer = zNew; - pCsr->nBuffer = nByte; - } - - u_strToUTF8( - pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ - &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ - &status /* Output success/failure */ - ); - } while( nByte>pCsr->nBuffer ); - - *ppToken = pCsr->zBuffer; - *pnBytes = nByte; - *piStartOffset = pCsr->aOffset[iStart]; - *piEndOffset = pCsr->aOffset[iEnd]; - *piPosition = pCsr->iToken++; - - return SQLITE_OK; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ - 0, /* xLanguageid */ -}; - -/* -** Set *ppModule to point at the implementation of the ICU tokenizer. -*/ -void sqlite3Fts3IcuTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &icuTokenizerModule; -} - -#endif /* defined(SQLITE_ENABLE_ICU) */ -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_porter.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_porter.c deleted file mode 100644 index 8fb4c25d..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_porter.c +++ /dev/null @@ -1,662 +0,0 @@ -/* -** 2006 September 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Implementation of the full-text-search tokenizer that implements -** a Porter stemmer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include -#include -#include - -#include "fts3_tokenizer.h" - -/* -** Class derived from sqlite3_tokenizer -*/ -typedef struct porter_tokenizer { - sqlite3_tokenizer base; /* Base class */ -} porter_tokenizer; - -/* -** Class derived from sqlite3_tokenizer_cursor -*/ -typedef struct porter_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *zInput; /* input we are tokenizing */ - int nInput; /* size of the input */ - int iOffset; /* current position in zInput */ - int iToken; /* index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAllocated; /* space allocated to zToken buffer */ -} porter_tokenizer_cursor; - - -/* -** Create a new tokenizer instance. -*/ -static int porterCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - porter_tokenizer *t; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int porterDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is zInput[0..nInput-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int porterOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, int nInput, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - porter_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->zInput = zInput; - if( zInput==0 ){ - c->nInput = 0; - }else if( nInput<0 ){ - c->nInput = (int)strlen(zInput); - }else{ - c->nInput = nInput; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->zToken = NULL; /* no space allocated, yet. */ - c->nAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** porterOpen() above. -*/ -static int porterClose(sqlite3_tokenizer_cursor *pCursor){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - sqlite3_free(c->zToken); - sqlite3_free(c); - return SQLITE_OK; -} -/* -** Vowel or consonant -*/ -static const char cType[] = { - 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 2, 1 -}; - -/* -** isConsonant() and isVowel() determine if their first character in -** the string they point to is a consonant or a vowel, according -** to Porter ruls. -** -** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. -** 'Y' is a consonant unless it follows another consonant, -** in which case it is a vowel. -** -** In these routine, the letters are in reverse order. So the 'y' rule -** is that 'y' is a consonant unless it is followed by another -** consonent. -*/ -static int isVowel(const char*); -static int isConsonant(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return j; - return z[1]==0 || isVowel(z + 1); -} -static int isVowel(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return 1-j; - return isConsonant(z + 1); -} - -/* -** Let any sequence of one or more vowels be represented by V and let -** C be sequence of one or more consonants. Then every word can be -** represented as: -** -** [C] (VC){m} [V] -** -** In prose: A word is an optional consonant followed by zero or -** vowel-consonant pairs followed by an optional vowel. "m" is the -** number of vowel consonant pairs. This routine computes the value -** of m for the first i bytes of a word. -** -** Return true if the m-value for z is 1 or more. In other words, -** return true if z contains at least one vowel that is followed -** by a consonant. -** -** In this routine z[] is in reverse order. So we are really looking -** for an instance of a consonant followed by a vowel. -*/ -static int m_gt_0(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* Like mgt0 above except we are looking for a value of m which is -** exactly 1 -*/ -static int m_eq_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 1; - while( isConsonant(z) ){ z++; } - return *z==0; -} - -/* Like mgt0 above except we are looking for a value of m>1 instead -** or m>0 -*/ -static int m_gt_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if there is a vowel anywhere within z[0..n-1] -*/ -static int hasVowel(const char *z){ - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if the word ends in a double consonant. -** -** The text is reversed here. So we are really looking at -** the first two characters of z[]. -*/ -static int doubleConsonant(const char *z){ - return isConsonant(z) && z[0]==z[1]; -} - -/* -** Return TRUE if the word ends with three letters which -** are consonant-vowel-consonent and where the final consonant -** is not 'w', 'x', or 'y'. -** -** The word is reversed here. So we are really checking the -** first three letters and the first one cannot be in [wxy]. -*/ -static int star_oh(const char *z){ - return - isConsonant(z) && - z[0]!='w' && z[0]!='x' && z[0]!='y' && - isVowel(z+1) && - isConsonant(z+2); -} - -/* -** If the word ends with zFrom and xCond() is true for the stem -** of the word that preceeds the zFrom ending, then change the -** ending to zTo. -** -** The input word *pz and zFrom are both in reverse order. zTo -** is in normal order. -** -** Return TRUE if zFrom matches. Return FALSE if zFrom does not -** match. Not that TRUE is returned even if xCond() fails and -** no substitution occurs. -*/ -static int stem( - char **pz, /* The word being stemmed (Reversed) */ - const char *zFrom, /* If the ending matches this... (Reversed) */ - const char *zTo, /* ... change the ending to this (not reversed) */ - int (*xCond)(const char*) /* Condition that must be true */ -){ - char *z = *pz; - while( *zFrom && *zFrom==*z ){ z++; zFrom++; } - if( *zFrom!=0 ) return 0; - if( xCond && !xCond(z) ) return 1; - while( *zTo ){ - *(--z) = *(zTo++); - } - *pz = z; - return 1; -} - -/* -** This is the fallback stemmer used when the porter stemmer is -** inappropriate. The input word is copied into the output with -** US-ASCII case folding. If the input word is too long (more -** than 20 bytes if it contains no digits or more than 6 bytes if -** it contains digits) then word is truncated to 20 or 6 bytes -** by taking 10 or 3 bytes from the beginning and end. -*/ -static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ - int i, mx, j; - int hasDigit = 0; - for(i=0; i='A' && c<='Z' ){ - zOut[i] = c - 'A' + 'a'; - }else{ - if( c>='0' && c<='9' ) hasDigit = 1; - zOut[i] = c; - } - } - mx = hasDigit ? 3 : 10; - if( nIn>mx*2 ){ - for(j=mx, i=nIn-mx; i=(int)sizeof(zReverse)-7 ){ - /* The word is too big or too small for the porter stemmer. - ** Fallback to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ - zReverse[j] = c + 'a' - 'A'; - }else if( c>='a' && c<='z' ){ - zReverse[j] = c; - }else{ - /* The use of a character not in [a-zA-Z] means that we fallback - ** to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - } - memset(&zReverse[sizeof(zReverse)-5], 0, 5); - z = &zReverse[j+1]; - - - /* Step 1a */ - if( z[0]=='s' ){ - if( - !stem(&z, "sess", "ss", 0) && - !stem(&z, "sei", "i", 0) && - !stem(&z, "ss", "ss", 0) - ){ - z++; - } - } - - /* Step 1b */ - z2 = z; - if( stem(&z, "dee", "ee", m_gt_0) ){ - /* Do nothing. The work was all in the test */ - }else if( - (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) - && z!=z2 - ){ - if( stem(&z, "ta", "ate", 0) || - stem(&z, "lb", "ble", 0) || - stem(&z, "zi", "ize", 0) ){ - /* Do nothing. The work was all in the test */ - }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ - z++; - }else if( m_eq_1(z) && star_oh(z) ){ - *(--z) = 'e'; - } - } - - /* Step 1c */ - if( z[0]=='y' && hasVowel(z+1) ){ - z[0] = 'i'; - } - - /* Step 2 */ - switch( z[1] ){ - case 'a': - if( !stem(&z, "lanoita", "ate", m_gt_0) ){ - stem(&z, "lanoit", "tion", m_gt_0); - } - break; - case 'c': - if( !stem(&z, "icne", "ence", m_gt_0) ){ - stem(&z, "icna", "ance", m_gt_0); - } - break; - case 'e': - stem(&z, "rezi", "ize", m_gt_0); - break; - case 'g': - stem(&z, "igol", "log", m_gt_0); - break; - case 'l': - if( !stem(&z, "ilb", "ble", m_gt_0) - && !stem(&z, "illa", "al", m_gt_0) - && !stem(&z, "iltne", "ent", m_gt_0) - && !stem(&z, "ile", "e", m_gt_0) - ){ - stem(&z, "ilsuo", "ous", m_gt_0); - } - break; - case 'o': - if( !stem(&z, "noitazi", "ize", m_gt_0) - && !stem(&z, "noita", "ate", m_gt_0) - ){ - stem(&z, "rota", "ate", m_gt_0); - } - break; - case 's': - if( !stem(&z, "msila", "al", m_gt_0) - && !stem(&z, "ssenevi", "ive", m_gt_0) - && !stem(&z, "ssenluf", "ful", m_gt_0) - ){ - stem(&z, "ssensuo", "ous", m_gt_0); - } - break; - case 't': - if( !stem(&z, "itila", "al", m_gt_0) - && !stem(&z, "itivi", "ive", m_gt_0) - ){ - stem(&z, "itilib", "ble", m_gt_0); - } - break; - } - - /* Step 3 */ - switch( z[0] ){ - case 'e': - if( !stem(&z, "etaci", "ic", m_gt_0) - && !stem(&z, "evita", "", m_gt_0) - ){ - stem(&z, "ezila", "al", m_gt_0); - } - break; - case 'i': - stem(&z, "itici", "ic", m_gt_0); - break; - case 'l': - if( !stem(&z, "laci", "ic", m_gt_0) ){ - stem(&z, "luf", "", m_gt_0); - } - break; - case 's': - stem(&z, "ssen", "", m_gt_0); - break; - } - - /* Step 4 */ - switch( z[1] ){ - case 'a': - if( z[0]=='l' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'c': - if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'e': - if( z[0]=='r' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'i': - if( z[0]=='c' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'l': - if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'n': - if( z[0]=='t' ){ - if( z[2]=='a' ){ - if( m_gt_1(z+3) ){ - z += 3; - } - }else if( z[2]=='e' ){ - if( !stem(&z, "tneme", "", m_gt_1) - && !stem(&z, "tnem", "", m_gt_1) - ){ - stem(&z, "tne", "", m_gt_1); - } - } - } - break; - case 'o': - if( z[0]=='u' ){ - if( m_gt_1(z+2) ){ - z += 2; - } - }else if( z[3]=='s' || z[3]=='t' ){ - stem(&z, "noi", "", m_gt_1); - } - break; - case 's': - if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 't': - if( !stem(&z, "eta", "", m_gt_1) ){ - stem(&z, "iti", "", m_gt_1); - } - break; - case 'u': - if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 'v': - case 'z': - if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - } - - /* Step 5a */ - if( z[0]=='e' ){ - if( m_gt_1(z+1) ){ - z++; - }else if( m_eq_1(z+1) && !star_oh(z+1) ){ - z++; - } - } - - /* Step 5b */ - if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ - z++; - } - - /* z[] is now the stemmed word in reverse order. Flip it back - ** around into forward order and return. - */ - *pnOut = i = (int)strlen(z); - zOut[i] = 0; - while( *z ){ - zOut[--i] = *(z++); - } -} - -/* -** Characters that can be part of a token. We assume any character -** whose value is greater than 0x80 (any UTF character) can be -** part of a token. In other words, delimiters all must have -** values of 0x7f or lower. -*/ -static const char porterIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ -}; -#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to porterOpen(). -*/ -static int porterNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ - const char **pzToken, /* OUT: *pzToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - const char *z = c->zInput; - - while( c->iOffsetnInput ){ - int iStartOffset, ch; - - /* Scan past delimiter characters */ - while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int n = c->iOffset-iStartOffset; - if( n>c->nAllocated ){ - char *pNew; - c->nAllocated = n+20; - pNew = sqlite3_realloc(c->zToken, c->nAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->zToken = pNew; - } - porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); - *pzToken = c->zToken; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the porter-stemmer tokenizer -*/ -static const sqlite3_tokenizer_module porterTokenizerModule = { - 0, - porterCreate, - porterDestroy, - porterOpen, - porterClose, - porterNext, - 0 -}; - -/* -** Allocate a new porter tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -void sqlite3Fts3PorterTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &porterTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_snippet.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_snippet.c deleted file mode 100644 index 115e98ab..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_snippet.c +++ /dev/null @@ -1,1724 +0,0 @@ -/* -** 2009 Oct 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -*/ - -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include - -/* -** Characters that may appear in the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ -#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ -#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ -#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ -#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ -#define FTS3_MATCHINFO_LCS 's' /* nCol values */ -#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ -#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */ - -/* -** The default value for the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_DEFAULT "pcx" - - -/* -** Used as an fts3ExprIterate() context when loading phrase doclists to -** Fts3Expr.aDoclist[]/nDoclist. -*/ -typedef struct LoadDoclistCtx LoadDoclistCtx; -struct LoadDoclistCtx { - Fts3Cursor *pCsr; /* FTS3 Cursor */ - int nPhrase; /* Number of phrases seen so far */ - int nToken; /* Number of tokens seen so far */ -}; - -/* -** The following types are used as part of the implementation of the -** fts3BestSnippet() routine. -*/ -typedef struct SnippetIter SnippetIter; -typedef struct SnippetPhrase SnippetPhrase; -typedef struct SnippetFragment SnippetFragment; - -struct SnippetIter { - Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ - int iCol; /* Extract snippet from this column */ - int nSnippet; /* Requested snippet length (in tokens) */ - int nPhrase; /* Number of phrases in query */ - SnippetPhrase *aPhrase; /* Array of size nPhrase */ - int iCurrent; /* First token of current snippet */ -}; - -struct SnippetPhrase { - int nToken; /* Number of tokens in phrase */ - char *pList; /* Pointer to start of phrase position list */ - int iHead; /* Next value in position list */ - char *pHead; /* Position list data following iHead */ - int iTail; /* Next value in trailing position list */ - char *pTail; /* Position list data following iTail */ -}; - -struct SnippetFragment { - int iCol; /* Column snippet is extracted from */ - int iPos; /* Index of first token in snippet */ - u64 covered; /* Mask of query phrases covered */ - u64 hlmask; /* Mask of snippet terms to highlight */ -}; - -/* -** This type is used as an fts3ExprIterate() context object while -** accumulating the data returned by the matchinfo() function. -*/ -typedef struct MatchInfo MatchInfo; -struct MatchInfo { - Fts3Cursor *pCursor; /* FTS3 Cursor */ - int nCol; /* Number of columns in table */ - int nPhrase; /* Number of matchable phrases in query */ - sqlite3_int64 nDoc; /* Number of docs in database */ - char flag; - u32 *aMatchinfo; /* Pre-allocated buffer */ -}; - -/* -** An instance of this structure is used to manage a pair of buffers, each -** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below -** for details. -*/ -struct MatchinfoBuffer { - u8 aRef[3]; - int nElem; - int bGlobal; /* Set if global data is loaded */ - char *zMatchinfo; - u32 aMatchinfo[1]; -}; - - -/* -** The snippet() and offsets() functions both return text values. An instance -** of the following structure is used to accumulate those values while the -** functions are running. See fts3StringAppend() for details. -*/ -typedef struct StrBuffer StrBuffer; -struct StrBuffer { - char *z; /* Pointer to buffer containing string */ - int n; /* Length of z in bytes (excl. nul-term) */ - int nAlloc; /* Allocated size of buffer z in bytes */ -}; - - -/************************************************************************* -** Start of MatchinfoBuffer code. -*/ - -/* -** Allocate a two-slot MatchinfoBuffer object. -*/ -static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ - MatchinfoBuffer *pRet; - int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); - int nStr = (int)strlen(zMatchinfo); - - pRet = sqlite3_malloc(nByte + nStr+1); - if( pRet ){ - memset(pRet, 0, nByte); - pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; - pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1); - pRet->nElem = nElem; - pRet->zMatchinfo = ((char*)pRet) + nByte; - memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); - pRet->aRef[0] = 1; - } - - return pRet; -} - -static void fts3MIBufferFree(void *p){ - MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); - - assert( (u32*)p==&pBuf->aMatchinfo[1] - || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2] - ); - if( (u32*)p==&pBuf->aMatchinfo[1] ){ - pBuf->aRef[1] = 0; - }else{ - pBuf->aRef[2] = 0; - } - - if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){ - sqlite3_free(pBuf); - } -} - -static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){ - void (*xRet)(void*) = 0; - u32 *aOut = 0; - - if( p->aRef[1]==0 ){ - p->aRef[1] = 1; - aOut = &p->aMatchinfo[1]; - xRet = fts3MIBufferFree; - } - else if( p->aRef[2]==0 ){ - p->aRef[2] = 1; - aOut = &p->aMatchinfo[p->nElem+2]; - xRet = fts3MIBufferFree; - }else{ - aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32)); - if( aOut ){ - xRet = sqlite3_free; - if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32)); - } - } - - *paOut = aOut; - return xRet; -} - -static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){ - p->bGlobal = 1; - memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32)); -} - -/* -** Free a MatchinfoBuffer object allocated using fts3MIBufferNew() -*/ -void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){ - if( p ){ - assert( p->aRef[0]==1 ); - p->aRef[0] = 0; - if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){ - sqlite3_free(p); - } - } -} - -/* -** End of MatchinfoBuffer code. -*************************************************************************/ - - -/* -** This function is used to help iterate through a position-list. A position -** list is a list of unique integers, sorted from smallest to largest. Each -** element of the list is represented by an FTS3 varint that takes the value -** of the difference between the current element and the previous one plus -** two. For example, to store the position-list: -** -** 4 9 113 -** -** the three varints: -** -** 6 7 106 -** -** are encoded. -** -** When this function is called, *pp points to the start of an element of -** the list. *piPos contains the value of the previous entry in the list. -** After it returns, *piPos contains the value of the next element of the -** list and *pp is advanced to the following varint. -*/ -static void fts3GetDeltaPosition(char **pp, int *piPos){ - int iVal; - *pp += fts3GetVarint32(*pp, &iVal); - *piPos += (iVal-2); -} - -/* -** Helper function for fts3ExprIterate() (see below). -*/ -static int fts3ExprIterate2( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int *piPhrase, /* Pointer to phrase counter */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int rc; /* Return code */ - int eType = pExpr->eType; /* Type of expression node pExpr */ - - if( eType!=FTSQUERY_PHRASE ){ - assert( pExpr->pLeft && pExpr->pRight ); - rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); - if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ - rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); - } - }else{ - rc = x(pExpr, *piPhrase, pCtx); - (*piPhrase)++; - } - return rc; -} - -/* -** Iterate through all phrase nodes in an FTS3 query, except those that -** are part of a sub-tree that is the right-hand-side of a NOT operator. -** For each phrase node found, the supplied callback function is invoked. -** -** If the callback function returns anything other than SQLITE_OK, -** the iteration is abandoned and the error code returned immediately. -** Otherwise, SQLITE_OK is returned after a callback has been made for -** all eligible phrase nodes. -*/ -static int fts3ExprIterate( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int iPhrase = 0; /* Variable used as the phrase counter */ - return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); -} - - -/* -** This is an fts3ExprIterate() callback used while loading the doclists -** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also -** fts3ExprLoadDoclists(). -*/ -static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - int rc = SQLITE_OK; - Fts3Phrase *pPhrase = pExpr->pPhrase; - LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; - - UNUSED_PARAMETER(iPhrase); - - p->nPhrase++; - p->nToken += pPhrase->nToken; - - return rc; -} - -/* -** Load the doclists for each phrase in the query associated with FTS3 cursor -** pCsr. -** -** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable -** phrases in the expression (all phrases except those directly or -** indirectly descended from the right-hand-side of a NOT operator). If -** pnToken is not NULL, then it is set to the number of tokens in all -** matchable phrases of the expression. -*/ -static int fts3ExprLoadDoclists( - Fts3Cursor *pCsr, /* Fts3 cursor for current query */ - int *pnPhrase, /* OUT: Number of phrases in query */ - int *pnToken /* OUT: Number of tokens in query */ -){ - int rc; /* Return Code */ - LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ - sCtx.pCsr = pCsr; - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); - if( pnPhrase ) *pnPhrase = sCtx.nPhrase; - if( pnToken ) *pnToken = sCtx.nToken; - return rc; -} - -static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - (*(int *)ctx)++; - pExpr->iPhrase = iPhrase; - return SQLITE_OK; -} -static int fts3ExprPhraseCount(Fts3Expr *pExpr){ - int nPhrase = 0; - (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); - return nPhrase; -} - -/* -** Advance the position list iterator specified by the first two -** arguments so that it points to the first element with a value greater -** than or equal to parameter iNext. -*/ -static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ - char *pIter = *ppIter; - if( pIter ){ - int iIter = *piIter; - - while( iIteriCurrent<0 ){ - /* The SnippetIter object has just been initialized. The first snippet - ** candidate always starts at offset 0 (even if this candidate has a - ** score of 0.0). - */ - pIter->iCurrent = 0; - - /* Advance the 'head' iterator of each phrase to the first offset that - ** is greater than or equal to (iNext+nSnippet). - */ - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); - } - }else{ - int iStart; - int iEnd = 0x7FFFFFFF; - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pHead && pPhrase->iHeadiHead; - } - } - if( iEnd==0x7FFFFFFF ){ - return 1; - } - - pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); - fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); - } - } - - return 0; -} - -/* -** Retrieve information about the current candidate snippet of snippet -** iterator pIter. -*/ -static void fts3SnippetDetails( - SnippetIter *pIter, /* Snippet iterator */ - u64 mCovered, /* Bitmask of phrases already covered */ - int *piToken, /* OUT: First token of proposed snippet */ - int *piScore, /* OUT: "Score" for this snippet */ - u64 *pmCover, /* OUT: Bitmask of phrases covered */ - u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ -){ - int iStart = pIter->iCurrent; /* First token of snippet */ - int iScore = 0; /* Score of this snippet */ - int i; /* Loop counter */ - u64 mCover = 0; /* Mask of phrases covered by this snippet */ - u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pTail ){ - char *pCsr = pPhrase->pTail; - int iCsr = pPhrase->iTail; - - while( iCsr<(iStart+pIter->nSnippet) ){ - int j; - u64 mPhrase = (u64)1 << i; - u64 mPos = (u64)1 << (iCsr - iStart); - assert( iCsr>=iStart && (iCsr - iStart)<=64 ); - assert( i>=0 && i<=64 ); - if( (mCover|mCovered)&mPhrase ){ - iScore++; - }else{ - iScore += 1000; - } - mCover |= mPhrase; - - for(j=0; jnToken; j++){ - mHighlight |= (mPos>>j); - } - - if( 0==(*pCsr & 0x0FE) ) break; - fts3GetDeltaPosition(&pCsr, &iCsr); - } - } - } - - /* Set the output variables before returning. */ - *piToken = iStart; - *piScore = iScore; - *pmCover = mCover; - *pmHighlight = mHighlight; -} - -/* -** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). -** Each invocation populates an element of the SnippetIter.aPhrase[] array. -*/ -static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ - SnippetIter *p = (SnippetIter *)ctx; - SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; - char *pCsr; - int rc; - - pPhrase->nToken = pExpr->pPhrase->nToken; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( pCsr ){ - int iFirst = 0; - pPhrase->pList = pCsr; - fts3GetDeltaPosition(&pCsr, &iFirst); - if( iFirst<0 ){ - rc = FTS_CORRUPT_VTAB; - }else{ - pPhrase->pHead = pCsr; - pPhrase->pTail = pCsr; - pPhrase->iHead = iFirst; - pPhrase->iTail = iFirst; - } - }else{ - assert( rc!=SQLITE_OK || ( - pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 - )); - } - - return rc; -} - -/* -** Select the fragment of text consisting of nFragment contiguous tokens -** from column iCol that represent the "best" snippet. The best snippet -** is the snippet with the highest score, where scores are calculated -** by adding: -** -** (a) +1 point for each occurrence of a matchable phrase in the snippet. -** -** (b) +1000 points for the first occurrence of each matchable phrase in -** the snippet for which the corresponding mCovered bit is not set. -** -** The selected snippet parameters are stored in structure *pFragment before -** returning. The score of the selected snippet is stored in *piScore -** before returning. -*/ -static int fts3BestSnippet( - int nSnippet, /* Desired snippet length */ - Fts3Cursor *pCsr, /* Cursor to create snippet for */ - int iCol, /* Index of column to create snippet from */ - u64 mCovered, /* Mask of phrases already covered */ - u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ - SnippetFragment *pFragment, /* OUT: Best snippet found */ - int *piScore /* OUT: Score of snippet pFragment */ -){ - int rc; /* Return Code */ - int nList; /* Number of phrases in expression */ - SnippetIter sIter; /* Iterates through snippet candidates */ - sqlite3_int64 nByte; /* Number of bytes of space to allocate */ - int iBestScore = -1; /* Best snippet score found so far */ - int i; /* Loop counter */ - - memset(&sIter, 0, sizeof(sIter)); - - /* Iterate through the phrases in the expression to count them. The same - ** callback makes sure the doclists are loaded for each phrase. - */ - rc = fts3ExprLoadDoclists(pCsr, &nList, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Now that it is known how many phrases there are, allocate and zero - ** the required space using malloc(). - */ - nByte = sizeof(SnippetPhrase) * nList; - sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte); - if( !sIter.aPhrase ){ - return SQLITE_NOMEM; - } - memset(sIter.aPhrase, 0, nByte); - - /* Initialize the contents of the SnippetIter object. Then iterate through - ** the set of phrases in the expression to populate the aPhrase[] array. - */ - sIter.pCsr = pCsr; - sIter.iCol = iCol; - sIter.nSnippet = nSnippet; - sIter.nPhrase = nList; - sIter.iCurrent = -1; - rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter); - if( rc==SQLITE_OK ){ - - /* Set the *pmSeen output variable. */ - for(i=0; iiCol = iCol; - while( !fts3SnippetNextCandidate(&sIter) ){ - int iPos; - int iScore; - u64 mCover; - u64 mHighlite; - fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover,&mHighlite); - assert( iScore>=0 ); - if( iScore>iBestScore ){ - pFragment->iPos = iPos; - pFragment->hlmask = mHighlite; - pFragment->covered = mCover; - iBestScore = iScore; - } - } - - *piScore = iBestScore; - } - sqlite3_free(sIter.aPhrase); - return rc; -} - - -/* -** Append a string to the string-buffer passed as the first argument. -** -** If nAppend is negative, then the length of the string zAppend is -** determined using strlen(). -*/ -static int fts3StringAppend( - StrBuffer *pStr, /* Buffer to append to */ - const char *zAppend, /* Pointer to data to append to buffer */ - int nAppend /* Size of zAppend in bytes (or -1) */ -){ - if( nAppend<0 ){ - nAppend = (int)strlen(zAppend); - } - - /* If there is insufficient space allocated at StrBuffer.z, use realloc() - ** to grow the buffer until so that it is big enough to accomadate the - ** appended data. - */ - if( pStr->n+nAppend+1>=pStr->nAlloc ){ - sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100; - char *zNew = sqlite3_realloc64(pStr->z, nAlloc); - if( !zNew ){ - return SQLITE_NOMEM; - } - pStr->z = zNew; - pStr->nAlloc = nAlloc; - } - assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) ); - - /* Append the data to the string buffer. */ - memcpy(&pStr->z[pStr->n], zAppend, nAppend); - pStr->n += nAppend; - pStr->z[pStr->n] = '\0'; - - return SQLITE_OK; -} - -/* -** The fts3BestSnippet() function often selects snippets that end with a -** query term. That is, the final term of the snippet is always a term -** that requires highlighting. For example, if 'X' is a highlighted term -** and '.' is a non-highlighted term, BestSnippet() may select: -** -** ........X.....X -** -** This function "shifts" the beginning of the snippet forward in the -** document so that there are approximately the same number of -** non-highlighted terms to the right of the final highlighted term as there -** are to the left of the first highlighted term. For example, to this: -** -** ....X.....X.... -** -** This is done as part of extracting the snippet text, not when selecting -** the snippet. Snippet selection is done based on doclists only, so there -** is no way for fts3BestSnippet() to know whether or not the document -** actually contains terms that follow the final highlighted term. -*/ -static int fts3SnippetShift( - Fts3Table *pTab, /* FTS3 table snippet comes from */ - int iLangid, /* Language id to use in tokenizing */ - int nSnippet, /* Number of tokens desired for snippet */ - const char *zDoc, /* Document text to extract snippet from */ - int nDoc, /* Size of buffer zDoc in bytes */ - int *piPos, /* IN/OUT: First token of snippet */ - u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ -){ - u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ - - if( hlmask ){ - int nLeft; /* Tokens to the left of first highlight */ - int nRight; /* Tokens to the right of last highlight */ - int nDesired; /* Ideal number of tokens to shift forward */ - - for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); - for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); - assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 ); - nDesired = (nLeft-nRight)/2; - - /* Ideally, the start of the snippet should be pushed forward in the - ** document nDesired tokens. This block checks if there are actually - ** nDesired tokens to the right of the snippet. If so, *piPos and - ** *pHlMask are updated to shift the snippet nDesired tokens to the - ** right. Otherwise, the snippet is shifted by the number of tokens - ** available. - */ - if( nDesired>0 ){ - int nShift; /* Number of tokens to shift snippet by */ - int iCurrent = 0; /* Token counter */ - int rc; /* Return Code */ - sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer_cursor *pC; - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - - /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) - ** or more tokens in zDoc/nDoc. - */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); - if( rc!=SQLITE_OK ){ - return rc; - } - while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ - const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0; - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); - } - pMod->xClose(pC); - if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } - - nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; - assert( nShift<=nDesired ); - if( nShift>0 ){ - *piPos += nShift; - *pHlmask = hlmask >> nShift; - } - } - } - return SQLITE_OK; -} - -/* -** Extract the snippet text for fragment pFragment from cursor pCsr and -** append it to string buffer pOut. -*/ -static int fts3SnippetText( - Fts3Cursor *pCsr, /* FTS3 Cursor */ - SnippetFragment *pFragment, /* Snippet to extract */ - int iFragment, /* Fragment number */ - int isLast, /* True for final fragment in snippet */ - int nSnippet, /* Number of tokens in extracted snippet */ - const char *zOpen, /* String inserted before highlighted term */ - const char *zClose, /* String inserted after highlighted term */ - const char *zEllipsis, /* String inserted between snippets */ - StrBuffer *pOut /* Write output here */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc; /* Return code */ - const char *zDoc; /* Document text to extract snippet from */ - int nDoc; /* Size of zDoc in bytes */ - int iCurrent = 0; /* Current token number of document */ - int iEnd = 0; /* Byte offset of end of current token */ - int isShiftDone = 0; /* True after snippet is shifted */ - int iPos = pFragment->iPos; /* First token of snippet */ - u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ - int iCol = pFragment->iCol+1; /* Query column to extract text from */ - sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ - - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - return SQLITE_OK; - } - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); - - /* Open a token cursor on the document. */ - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); - if( rc!=SQLITE_OK ){ - return rc; - } - - while( rc==SQLITE_OK ){ - const char *ZDUMMY; /* Dummy argument used with tokenizer */ - int DUMMY1 = -1; /* Dummy argument used with tokenizer */ - int iBegin = 0; /* Offset in zDoc of start of token */ - int iFin = 0; /* Offset in zDoc of end of token */ - int isHighlight = 0; /* True for highlighted terms */ - - /* Variable DUMMY1 is initialized to a negative value above. Elsewhere - ** in the FTS code the variable that the third argument to xNext points to - ** is initialized to zero before the first (*but not necessarily - ** subsequent*) call to xNext(). This is done for a particular application - ** that needs to know whether or not the tokenizer is being used for - ** snippet generation or for some other purpose. - ** - ** Extreme care is required when writing code to depend on this - ** initialization. It is not a documented part of the tokenizer interface. - ** If a tokenizer is used directly by any code outside of FTS, this - ** convention might not be respected. */ - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - /* Special case - the last token of the snippet is also the last token - ** of the column. Append any punctuation that occurred between the end - ** of the previous token and the end of the document to the output. - ** Then break out of the loop. */ - rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); - } - break; - } - if( iCurrentiLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask - ); - isShiftDone = 1; - - /* Now that the shift has been done, check if the initial "..." are - ** required. They are required if (a) this is not the first fragment, - ** or (b) this fragment does not begin at position 0 of its column. - */ - if( rc==SQLITE_OK ){ - if( iPos>0 || iFragment>0 ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - }else if( iBegin ){ - rc = fts3StringAppend(pOut, zDoc, iBegin); - } - } - if( rc!=SQLITE_OK || iCurrent=(iPos+nSnippet) ){ - if( isLast ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - } - break; - } - - /* Set isHighlight to true if this term should be highlighted. */ - isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; - - if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); - if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); - - iEnd = iFin; - } - - pMod->xClose(pC); - return rc; -} - - -/* -** This function is used to count the entries in a column-list (a -** delta-encoded list of term offsets within a single column of a single -** row). When this function is called, *ppCollist should point to the -** beginning of the first varint in the column-list (the varint that -** contains the position of the first matching term in the column data). -** Before returning, *ppCollist is set to point to the first byte after -** the last varint in the column-list (either the 0x00 signifying the end -** of the position-list, or the 0x01 that precedes the column number of -** the next column in the position-list). -** -** The number of elements in the column-list is returned. -*/ -static int fts3ColumnlistCount(char **ppCollist){ - char *pEnd = *ppCollist; - char c = 0; - int nEntry = 0; - - /* A column-list is terminated by either a 0x01 or 0x00. */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - if( !c ) nEntry++; - } - - *ppCollist = pEnd; - return nEntry; -} - -/* -** This function gathers 'y' or 'b' data for a single phrase. -*/ -static int fts3ExprLHits( - Fts3Expr *pExpr, /* Phrase expression node */ - MatchInfo *p /* Matchinfo context */ -){ - Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab; - int iStart; - Fts3Phrase *pPhrase = pExpr->pPhrase; - char *pIter = pPhrase->doclist.pList; - int iCol = 0; - - assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS ); - if( p->flag==FTS3_MATCHINFO_LHITS ){ - iStart = pExpr->iPhrase * p->nCol; - }else{ - iStart = pExpr->iPhrase * ((p->nCol + 31) / 32); - } - - while( 1 ){ - int nHit = fts3ColumnlistCount(&pIter); - if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ - if( p->flag==FTS3_MATCHINFO_LHITS ){ - p->aMatchinfo[iStart + iCol] = (u32)nHit; - }else if( nHit ){ - p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F)); - } - } - assert( *pIter==0x00 || *pIter==0x01 ); - if( *pIter!=0x01 ) break; - pIter++; - pIter += fts3GetVarint32(pIter, &iCol); - if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB; - } - return SQLITE_OK; -} - -/* -** Gather the results for matchinfo directives 'y' and 'b'. -*/ -static int fts3ExprLHitGather( - Fts3Expr *pExpr, - MatchInfo *p -){ - int rc = SQLITE_OK; - assert( (pExpr->pLeft==0)==(pExpr->pRight==0) ); - if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ - if( pExpr->pLeft ){ - rc = fts3ExprLHitGather(pExpr->pLeft, p); - if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p); - }else{ - rc = fts3ExprLHits(pExpr, p); - } - } - return rc; -} - -/* -** fts3ExprIterate() callback used to collect the "global" matchinfo stats -** for a single query. -** -** fts3ExprIterate() callback to load the 'global' elements of a -** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements -** of the matchinfo array that are constant for all rows returned by the -** current query. -** -** Argument pCtx is actually a pointer to a struct of type MatchInfo. This -** function populates Matchinfo.aMatchinfo[] as follows: -** -** for(iCol=0; iColpCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol] - ); -} - -/* -** fts3ExprIterate() callback used to collect the "local" part of the -** FTS3_MATCHINFO_HITS array. The local stats are those elements of the -** array that are different for each row returned by the query. -*/ -static int fts3ExprLocalHitsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - int rc = SQLITE_OK; - MatchInfo *p = (MatchInfo *)pCtx; - int iStart = iPhrase * p->nCol * 3; - int i; - - for(i=0; inCol && rc==SQLITE_OK; i++){ - char *pCsr; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr); - if( pCsr ){ - p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr); - }else{ - p->aMatchinfo[iStart+i*3] = 0; - } - } - - return rc; -} - -static int fts3MatchinfoCheck( - Fts3Table *pTab, - char cArg, - char **pzErr -){ - if( (cArg==FTS3_MATCHINFO_NPHRASE) - || (cArg==FTS3_MATCHINFO_NCOL) - || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) - || (cArg==FTS3_MATCHINFO_LCS) - || (cArg==FTS3_MATCHINFO_HITS) - || (cArg==FTS3_MATCHINFO_LHITS) - || (cArg==FTS3_MATCHINFO_LHITS_BM) - ){ - return SQLITE_OK; - } - sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); - return SQLITE_ERROR; -} - -static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ - int nVal; /* Number of integers output by cArg */ - - switch( cArg ){ - case FTS3_MATCHINFO_NDOC: - case FTS3_MATCHINFO_NPHRASE: - case FTS3_MATCHINFO_NCOL: - nVal = 1; - break; - - case FTS3_MATCHINFO_AVGLENGTH: - case FTS3_MATCHINFO_LENGTH: - case FTS3_MATCHINFO_LCS: - nVal = pInfo->nCol; - break; - - case FTS3_MATCHINFO_LHITS: - nVal = pInfo->nCol * pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_LHITS_BM: - nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32); - break; - - default: - assert( cArg==FTS3_MATCHINFO_HITS ); - nVal = pInfo->nCol * pInfo->nPhrase * 3; - break; - } - - return nVal; -} - -static int fts3MatchinfoSelectDoctotal( - Fts3Table *pTab, - sqlite3_stmt **ppStmt, - sqlite3_int64 *pnDoc, - const char **paLen -){ - sqlite3_stmt *pStmt; - const char *a; - sqlite3_int64 nDoc; - - if( !*ppStmt ){ - int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); - if( rc!=SQLITE_OK ) return rc; - } - pStmt = *ppStmt; - assert( sqlite3_data_count(pStmt)==1 ); - - a = sqlite3_column_blob(pStmt, 0); - a += sqlite3Fts3GetVarint(a, &nDoc); - if( nDoc==0 ) return FTS_CORRUPT_VTAB; - *pnDoc = (u32)nDoc; - - if( paLen ) *paLen = a; - return SQLITE_OK; -} - -/* -** An instance of the following structure is used to store state while -** iterating through a multi-column position-list corresponding to the -** hits for a single phrase on a single row in order to calculate the -** values for a matchinfo() FTS3_MATCHINFO_LCS request. -*/ -typedef struct LcsIterator LcsIterator; -struct LcsIterator { - Fts3Expr *pExpr; /* Pointer to phrase expression */ - int iPosOffset; /* Tokens count up to end of this phrase */ - char *pRead; /* Cursor used to iterate through aDoclist */ - int iPos; /* Current position */ -}; - -/* -** If LcsIterator.iCol is set to the following value, the iterator has -** finished iterating through all offsets for all columns. -*/ -#define LCS_ITERATOR_FINISHED 0x7FFFFFFF; - -static int fts3MatchinfoLcsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number (numbered from zero) */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - LcsIterator *aIter = (LcsIterator *)pCtx; - aIter[iPhrase].pExpr = pExpr; - return SQLITE_OK; -} - -/* -** Advance the iterator passed as an argument to the next position. Return -** 1 if the iterator is at EOF or if it now points to the start of the -** position list for the next column. -*/ -static int fts3LcsIteratorAdvance(LcsIterator *pIter){ - char *pRead = pIter->pRead; - sqlite3_int64 iRead; - int rc = 0; - - pRead += sqlite3Fts3GetVarint(pRead, &iRead); - if( iRead==0 || iRead==1 ){ - pRead = 0; - rc = 1; - }else{ - pIter->iPos += (int)(iRead-2); - } - - pIter->pRead = pRead; - return rc; -} - -/* -** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. -** -** If the call is successful, the longest-common-substring lengths for each -** column are written into the first nCol elements of the pInfo->aMatchinfo[] -** array before returning. SQLITE_OK is returned in this case. -** -** Otherwise, if an error occurs, an SQLite error code is returned and the -** data written to the first nCol elements of pInfo->aMatchinfo[] is -** undefined. -*/ -static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ - LcsIterator *aIter; - int i; - int iCol; - int nToken = 0; - int rc = SQLITE_OK; - - /* Allocate and populate the array of LcsIterator objects. The array - ** contains one element for each matchable phrase in the query. - **/ - aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase); - if( !aIter ) return SQLITE_NOMEM; - memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase); - (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - nToken -= pIter->pExpr->pPhrase->nToken; - pIter->iPosOffset = nToken; - } - - for(iCol=0; iColnCol; iCol++){ - int nLcs = 0; /* LCS value for this column */ - int nLive = 0; /* Number of iterators in aIter not at EOF */ - - for(i=0; inPhrase; i++){ - LcsIterator *pIt = &aIter[i]; - rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead); - if( rc!=SQLITE_OK ) goto matchinfo_lcs_out; - if( pIt->pRead ){ - pIt->iPos = pIt->iPosOffset; - fts3LcsIteratorAdvance(pIt); - if( pIt->pRead==0 ){ - rc = FTS_CORRUPT_VTAB; - goto matchinfo_lcs_out; - } - nLive++; - } - } - - while( nLive>0 ){ - LcsIterator *pAdv = 0; /* The iterator to advance by one position */ - int nThisLcs = 0; /* LCS for the current iterator positions */ - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - if( pIter->pRead==0 ){ - /* This iterator is already at EOF for this column. */ - nThisLcs = 0; - }else{ - if( pAdv==0 || pIter->iPosiPos ){ - pAdv = pIter; - } - if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){ - nThisLcs++; - }else{ - nThisLcs = 1; - } - if( nThisLcs>nLcs ) nLcs = nThisLcs; - } - } - if( fts3LcsIteratorAdvance(pAdv) ) nLive--; - } - - pInfo->aMatchinfo[iCol] = nLcs; - } - - matchinfo_lcs_out: - sqlite3_free(aIter); - return rc; -} - -/* -** Populate the buffer pInfo->aMatchinfo[] with an array of integers to -** be returned by the matchinfo() function. Argument zArg contains the -** format string passed as the second argument to matchinfo (or the -** default value "pcx" if no second argument was specified). The format -** string has already been validated and the pInfo->aMatchinfo[] array -** is guaranteed to be large enough for the output. -** -** If bGlobal is true, then populate all fields of the matchinfo() output. -** If it is false, then assume that those fields that do not change between -** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) -** have already been populated. -** -** Return SQLITE_OK if successful, or an SQLite error code if an error -** occurs. If a value other than SQLITE_OK is returned, the state the -** pInfo->aMatchinfo[] buffer is left in is undefined. -*/ -static int fts3MatchinfoValues( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - int bGlobal, /* True to grab the global stats */ - MatchInfo *pInfo, /* Matchinfo context object */ - const char *zArg /* Matchinfo format string */ -){ - int rc = SQLITE_OK; - int i; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_stmt *pSelect = 0; - - for(i=0; rc==SQLITE_OK && zArg[i]; i++){ - pInfo->flag = zArg[i]; - switch( zArg[i] ){ - case FTS3_MATCHINFO_NPHRASE: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_NCOL: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; - break; - - case FTS3_MATCHINFO_NDOC: - if( bGlobal ){ - sqlite3_int64 nDoc = 0; - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0); - pInfo->aMatchinfo[0] = (u32)nDoc; - } - break; - - case FTS3_MATCHINFO_AVGLENGTH: - if( bGlobal ){ - sqlite3_int64 nDoc; /* Number of rows in table */ - const char *a; /* Aggregate column length array */ - - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); - if( rc==SQLITE_OK ){ - int iCol; - for(iCol=0; iColnCol; iCol++){ - u32 iVal; - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarint(a, &nToken); - iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); - pInfo->aMatchinfo[iCol] = iVal; - } - } - } - break; - - case FTS3_MATCHINFO_LENGTH: { - sqlite3_stmt *pSelectDocsize = 0; - rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); - if( rc==SQLITE_OK ){ - int iCol; - const char *a = sqlite3_column_blob(pSelectDocsize, 0); - for(iCol=0; iColnCol; iCol++){ - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarint(a, &nToken); - pInfo->aMatchinfo[iCol] = (u32)nToken; - } - } - sqlite3_reset(pSelectDocsize); - break; - } - - case FTS3_MATCHINFO_LCS: - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3MatchinfoLcs(pCsr, pInfo); - } - break; - - case FTS3_MATCHINFO_LHITS_BM: - case FTS3_MATCHINFO_LHITS: { - int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); - memset(pInfo->aMatchinfo, 0, nZero); - rc = fts3ExprLHitGather(pCsr->pExpr, pInfo); - break; - } - - default: { - Fts3Expr *pExpr; - assert( zArg[i]==FTS3_MATCHINFO_HITS ); - pExpr = pCsr->pExpr; - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc!=SQLITE_OK ) break; - if( bGlobal ){ - if( pCsr->pDeferred ){ - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0); - if( rc!=SQLITE_OK ) break; - } - rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); - sqlite3Fts3EvalTestDeferred(pCsr, &rc); - if( rc!=SQLITE_OK ) break; - } - (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); - break; - } - } - - pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); - } - - sqlite3_reset(pSelect); - return rc; -} - - -/* -** Populate pCsr->aMatchinfo[] with data for the current row. The -** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). -*/ -static void fts3GetMatchinfo( - sqlite3_context *pCtx, /* Return results here */ - Fts3Cursor *pCsr, /* FTS3 Cursor object */ - const char *zArg /* Second argument to matchinfo() function */ -){ - MatchInfo sInfo; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int bGlobal = 0; /* Collect 'global' stats as well as local */ - - u32 *aOut = 0; - void (*xDestroyOut)(void*) = 0; - - memset(&sInfo, 0, sizeof(MatchInfo)); - sInfo.pCursor = pCsr; - sInfo.nCol = pTab->nColumn; - - /* If there is cached matchinfo() data, but the format string for the - ** cache does not match the format string for this request, discard - ** the cached data. */ - if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){ - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - pCsr->pMIBuffer = 0; - } - - /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the - ** matchinfo function has been called for this query. In this case - ** allocate the array used to accumulate the matchinfo data and - ** initialize those elements that are constant for every row. - */ - if( pCsr->pMIBuffer==0 ){ - int nMatchinfo = 0; /* Number of u32 elements in match-info */ - int i; /* Used to iterate through zArg */ - - /* Determine the number of phrases in the query */ - pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); - sInfo.nPhrase = pCsr->nPhrase; - - /* Determine the number of integers in the buffer returned by this call. */ - for(i=0; zArg[i]; i++){ - char *zErr = 0; - if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ - sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); - return; - } - nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); - } - - /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ - pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg); - if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM; - - pCsr->isMatchinfoNeeded = 1; - bGlobal = 1; - } - - if( rc==SQLITE_OK ){ - xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut); - if( xDestroyOut==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - sInfo.aMatchinfo = aOut; - sInfo.nPhrase = pCsr->nPhrase; - rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); - if( bGlobal ){ - fts3MIBufferSetGlobal(pCsr->pMIBuffer); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - if( xDestroyOut ) xDestroyOut(aOut); - }else{ - int n = pCsr->pMIBuffer->nElem * sizeof(u32); - sqlite3_result_blob(pCtx, aOut, n, xDestroyOut); - } -} - -/* -** Implementation of snippet() function. -*/ -void sqlite3Fts3Snippet( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr, /* Cursor object */ - const char *zStart, /* Snippet start text - "" */ - const char *zEnd, /* Snippet end text - "" */ - const char *zEllipsis, /* Snippet ellipsis text - "..." */ - int iCol, /* Extract snippet from this column */ - int nToken /* Approximate number of tokens in snippet */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int i; - StrBuffer res = {0, 0, 0}; - - /* The returned text includes up to four fragments of text extracted from - ** the data in the current row. The first iteration of the for(...) loop - ** below attempts to locate a single fragment of text nToken tokens in - ** size that contains at least one instance of all phrases in the query - ** expression that appear in the current row. If such a fragment of text - ** cannot be found, the second iteration of the loop attempts to locate - ** a pair of fragments, and so on. - */ - int nSnippet = 0; /* Number of fragments in this snippet */ - SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ - int nFToken = -1; /* Number of tokens in each fragment */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - /* Limit the snippet length to 64 tokens. */ - if( nToken<-64 ) nToken = -64; - if( nToken>+64 ) nToken = +64; - - for(nSnippet=1; 1; nSnippet++){ - - int iSnip; /* Loop counter 0..nSnippet-1 */ - u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ - u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ - - if( nToken>=0 ){ - nFToken = (nToken+nSnippet-1) / nSnippet; - }else{ - nFToken = -1 * nToken; - } - - for(iSnip=0; iSnipnColumn; iRead++){ - SnippetFragment sF = {0, 0, 0, 0}; - int iS = 0; - if( iCol>=0 && iRead!=iCol ) continue; - - /* Find the best snippet of nFToken tokens in column iRead. */ - rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); - if( rc!=SQLITE_OK ){ - goto snippet_out; - } - if( iS>iBestScore ){ - *pFragment = sF; - iBestScore = iS; - } - } - - mCovered |= pFragment->covered; - } - - /* If all query phrases seen by fts3BestSnippet() are present in at least - ** one of the nSnippet snippet fragments, break out of the loop. - */ - assert( (mCovered&mSeen)==mCovered ); - if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; - } - - assert( nFToken>0 ); - - for(i=0; ipCsr, pExpr, p->iCol, &pList); - nTerm = pExpr->pPhrase->nToken; - if( pList ){ - fts3GetDeltaPosition(&pList, &iPos); - assert( iPos>=0 ); - } - - for(iTerm=0; iTermaTerm[p->iTerm++]; - pT->iOff = nTerm-iTerm-1; - pT->pList = pList; - pT->iPos = iPos; - } - - return rc; -} - -/* -** Implementation of offsets() function. -*/ -void sqlite3Fts3Offsets( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr /* Cursor object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; - int rc; /* Return Code */ - int nToken; /* Number of tokens in query */ - int iCol; /* Column currently being processed */ - StrBuffer res = {0, 0, 0}; /* Result string */ - TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - memset(&sCtx, 0, sizeof(sCtx)); - assert( pCsr->isRequireSeek==0 ); - - /* Count the number of terms in the query */ - rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); - if( rc!=SQLITE_OK ) goto offsets_out; - - /* Allocate the array of TermOffset iterators. */ - sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken); - if( 0==sCtx.aTerm ){ - rc = SQLITE_NOMEM; - goto offsets_out; - } - sCtx.iDocid = pCsr->iPrevId; - sCtx.pCsr = pCsr; - - /* Loop through the table columns, appending offset information to - ** string-buffer res for each column. - */ - for(iCol=0; iColnColumn; iCol++){ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ - const char *ZDUMMY; /* Dummy argument used with xNext() */ - int NDUMMY = 0; /* Dummy argument used with xNext() */ - int iStart = 0; - int iEnd = 0; - int iCurrent = 0; - const char *zDoc; - int nDoc; - - /* Initialize the contents of sCtx.aTerm[] for column iCol. There is - ** no way that this operation can fail, so the return code from - ** fts3ExprIterate() can be discarded. - */ - sCtx.iCol = iCol; - sCtx.iTerm = 0; - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx); - - /* Retreive the text stored in column iCol. If an SQL NULL is stored - ** in column iCol, jump immediately to the next iteration of the loop. - ** If an OOM occurs while retrieving the data (this can happen if SQLite - ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM - ** to the caller. - */ - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ - continue; - } - rc = SQLITE_NOMEM; - goto offsets_out; - } - - /* Initialize a tokenizer iterator to iterate through column iCol. */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, - zDoc, nDoc, &pC - ); - if( rc!=SQLITE_OK ) goto offsets_out; - - rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - while( rc==SQLITE_OK ){ - int i; /* Used to loop through terms */ - int iMinPos = 0x7FFFFFFF; /* Position of next token */ - TermOffset *pTerm = 0; /* TermOffset associated with next token */ - - for(i=0; ipList && (pT->iPos-pT->iOff)iPos-pT->iOff; - pTerm = pT; - } - } - - if( !pTerm ){ - /* All offsets for this column have been gathered. */ - rc = SQLITE_DONE; - }else{ - assert( iCurrent<=iMinPos ); - if( 0==(0xFE&*pTerm->pList) ){ - pTerm->pList = 0; - }else{ - fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); - } - while( rc==SQLITE_OK && iCurrentxNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - } - if( rc==SQLITE_OK ){ - char aBuffer[64]; - sqlite3_snprintf(sizeof(aBuffer), aBuffer, - "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart - ); - rc = fts3StringAppend(&res, aBuffer, -1); - }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - } - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - - pMod->xClose(pC); - if( rc!=SQLITE_OK ) goto offsets_out; - } - - offsets_out: - sqlite3_free(sCtx.aTerm); - assert( rc!=SQLITE_DONE ); - sqlite3Fts3SegmentsClose(pTab); - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - sqlite3_free(res.z); - }else{ - sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); - } - return; -} - -/* -** Implementation of matchinfo() function. -*/ -void sqlite3Fts3Matchinfo( - sqlite3_context *pContext, /* Function call context */ - Fts3Cursor *pCsr, /* FTS3 table cursor */ - const char *zArg /* Second arg to matchinfo() function */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - const char *zFormat; - - if( zArg ){ - zFormat = zArg; - }else{ - zFormat = FTS3_MATCHINFO_DEFAULT; - } - - if( !pCsr->pExpr ){ - sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); - return; - }else{ - /* Retrieve matchinfo() data. */ - fts3GetMatchinfo(pContext, pCsr, zFormat); - sqlite3Fts3SegmentsClose(pTab); - } -} - -#endif diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenize_vtab.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenize_vtab.c deleted file mode 100644 index b5bf8add..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenize_vtab.c +++ /dev/null @@ -1,455 +0,0 @@ -/* -** 2013 Apr 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code for the "fts3tokenize" virtual table module. -** An fts3tokenize virtual table is created as follows: -** -** CREATE VIRTUAL TABLE USING fts3tokenize( -** , , ... -** ); -** -** The table created has the following schema: -** -** CREATE TABLE (input, token, start, end, position) -** -** When queried, the query must include a WHERE clause of type: -** -** input = -** -** The virtual table module tokenizes this , using the FTS3 -** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE -** statement and returns one row for each token in the result. With -** fields set as follows: -** -** input: Always set to a copy of -** token: A token from the input. -** start: Byte offset of the token within the input . -** end: Byte offset of the byte immediately following the end of the -** token within the input string. -** pos: Token offset of token within input. -** -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include - -typedef struct Fts3tokTable Fts3tokTable; -typedef struct Fts3tokCursor Fts3tokCursor; - -/* -** Virtual table structure. -*/ -struct Fts3tokTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - const sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer *pTok; -}; - -/* -** Virtual table cursor structure. -*/ -struct Fts3tokCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - char *zInput; /* Input string */ - sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */ - int iRowid; /* Current 'rowid' value */ - const char *zToken; /* Current 'token' value */ - int nToken; /* Size of zToken in bytes */ - int iStart; /* Current 'start' value */ - int iEnd; /* Current 'end' value */ - int iPos; /* Current 'pos' value */ -}; - -/* -** Query FTS for the tokenizer implementation named zName. -*/ -static int fts3tokQueryTokenizer( - Fts3Hash *pHash, - const char *zName, - const sqlite3_tokenizer_module **pp, - char **pzErr -){ - sqlite3_tokenizer_module *p; - int nName = (int)strlen(zName); - - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - if( !p ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName); - return SQLITE_ERROR; - } - - *pp = p; - return SQLITE_OK; -} - -/* -** The second argument, argv[], is an array of pointers to nul-terminated -** strings. This function makes a copy of the array and strings into a -** single block of memory. It then dequotes any of the strings that appear -** to be quoted. -** -** If successful, output parameter *pazDequote is set to point at the -** array of dequoted strings and SQLITE_OK is returned. The caller is -** responsible for eventually calling sqlite3_free() to free the array -** in this case. Or, if an error occurs, an SQLite error code is returned. -** The final value of *pazDequote is undefined in this case. -*/ -static int fts3tokDequoteArray( - int argc, /* Number of elements in argv[] */ - const char * const *argv, /* Input array */ - char ***pazDequote /* Output array */ -){ - int rc = SQLITE_OK; /* Return code */ - if( argc==0 ){ - *pazDequote = 0; - }else{ - int i; - int nByte = 0; - char **azDequote; - - for(i=0; ixCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok); - } - - if( rc==SQLITE_OK ){ - pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - memset(pTab, 0, sizeof(Fts3tokTable)); - pTab->pMod = pMod; - pTab->pTok = pTok; - *ppVtab = &pTab->base; - }else{ - if( pTok ){ - pMod->xDestroy(pTok); - } - } - - sqlite3_free(azDequote); - return rc; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3tokTable *pTab = (Fts3tokTable *)pVtab; - - pTab->pMod->xDestroy(pTab->pTok); - sqlite3_free(pTab); - return SQLITE_OK; -} - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3tokBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - UNUSED_PARAMETER(pVTab); - - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable - && pInfo->aConstraint[i].iColumn==0 - && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ - ){ - pInfo->idxNum = 1; - pInfo->aConstraintUsage[i].argvIndex = 1; - pInfo->aConstraintUsage[i].omit = 1; - pInfo->estimatedCost = 1; - return SQLITE_OK; - } - } - - pInfo->idxNum = 0; - assert( pInfo->estimatedCost>1000000.0 ); - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3tokCursor *pCsr; - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3tokCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Reset the tokenizer cursor passed as the only argument. As if it had -** just been returned by fts3tokOpenMethod(). -*/ -static void fts3tokResetCursor(Fts3tokCursor *pCsr){ - if( pCsr->pCsr ){ - Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab); - pTab->pMod->xClose(pCsr->pCsr); - pCsr->pCsr = 0; - } - sqlite3_free(pCsr->zInput); - pCsr->zInput = 0; - pCsr->zToken = 0; - pCsr->nToken = 0; - pCsr->iStart = 0; - pCsr->iEnd = 0; - pCsr->iPos = 0; - pCsr->iRowid = 0; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - fts3tokResetCursor(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - int rc; /* Return code */ - - pCsr->iRowid++; - rc = pTab->pMod->xNext(pCsr->pCsr, - &pCsr->zToken, &pCsr->nToken, - &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos - ); - - if( rc!=SQLITE_OK ){ - fts3tokResetCursor(pCsr); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3tokFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc = SQLITE_ERROR; - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - fts3tokResetCursor(pCsr); - if( idxNum==1 ){ - const char *zByte = (const char *)sqlite3_value_text(apVal[0]); - int nByte = sqlite3_value_bytes(apVal[0]); - pCsr->zInput = sqlite3_malloc(nByte+1); - if( pCsr->zInput==0 ){ - rc = SQLITE_NOMEM; - }else{ - memcpy(pCsr->zInput, zByte, nByte); - pCsr->zInput[nByte] = 0; - rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr); - if( rc==SQLITE_OK ){ - pCsr->pCsr->pTokenizer = pTab->pTok; - } - } - } - - if( rc!=SQLITE_OK ) return rc; - return fts3tokNextMethod(pCursor); -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - return (pCsr->zToken==0); -} - -/* -** xColumn - Return a column value. -*/ -static int fts3tokColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - /* CREATE TABLE x(input, token, start, end, position) */ - switch( iCol ){ - case 0: - sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT); - break; - case 1: - sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT); - break; - case 2: - sqlite3_result_int(pCtx, pCsr->iStart); - break; - case 3: - sqlite3_result_int(pCtx, pCsr->iEnd); - break; - default: - assert( iCol==4 ); - sqlite3_result_int(pCtx, pCsr->iPos); - break; - } - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3tokRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - *pRowid = (sqlite3_int64)pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3tok module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ - static const sqlite3_module fts3tok_module = { - 0, /* iVersion */ - fts3tokConnectMethod, /* xCreate */ - fts3tokConnectMethod, /* xConnect */ - fts3tokBestIndexMethod, /* xBestIndex */ - fts3tokDisconnectMethod, /* xDisconnect */ - fts3tokDisconnectMethod, /* xDestroy */ - fts3tokOpenMethod, /* xOpen */ - fts3tokCloseMethod, /* xClose */ - fts3tokFilterMethod, /* xFilter */ - fts3tokNextMethod, /* xNext */ - fts3tokEofMethod, /* xEof */ - fts3tokColumnMethod, /* xColumn */ - fts3tokRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0 /* xShadowName */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.c deleted file mode 100644 index bfc36af3..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.c +++ /dev/null @@ -1,516 +0,0 @@ -/* -** 2007 June 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is part of an SQLite module implementing full-text search. -** This particular file implements the generic tokenizer interface. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include - -/* -** Return true if the two-argument version of fts3_tokenizer() -** has been activated via a prior call to sqlite3_db_config(db, -** SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, 0); -*/ -static int fts3TokenizerEnabled(sqlite3_context *context){ - sqlite3 *db = sqlite3_context_db_handle(context); - int isEnabled = 0; - sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER,-1,&isEnabled); - return isEnabled; -} - -/* -** Implementation of the SQL scalar function for accessing the underlying -** hash table. This function may be called as follows: -** -** SELECT (); -** SELECT (, ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer'). -** -** If the argument is specified, it must be a blob value -** containing a pointer to be stored as the hash data corresponding -** to the string . If is not specified, then -** the string must already exist in the has table. Otherwise, -** an error is returned. -** -** Whether or not the argument is specified, the value returned -** is a blob containing the pointer stored as the hash data corresponding -** to string (after the hash-table is updated, if applicable). -*/ -static void fts3TokenizerFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - void *pPtr = 0; - const unsigned char *zName; - int nName; - - assert( argc==1 || argc==2 ); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - - zName = sqlite3_value_text(argv[0]); - nName = sqlite3_value_bytes(argv[0])+1; - - if( argc==2 ){ - if( fts3TokenizerEnabled(context) ){ - void *pOld; - int n = sqlite3_value_bytes(argv[1]); - if( zName==0 || n!=sizeof(pPtr) ){ - sqlite3_result_error(context, "argument type mismatch", -1); - return; - } - pPtr = *(void **)sqlite3_value_blob(argv[1]); - pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); - if( pOld==pPtr ){ - sqlite3_result_error(context, "out of memory", -1); - } - }else{ - sqlite3_result_error(context, "fts3tokenize disabled", -1); - return; - } - }else{ - if( zName ){ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); - } - if( !pPtr ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - } - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); -} - -int sqlite3Fts3IsIdChar(char c){ - static const char isFtsIdChar[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ - }; - return (c&0x80 || isFtsIdChar[(int)(c)]); -} - -const char *sqlite3Fts3NextToken(const char *zStr, int *pn){ - const char *z1; - const char *z2 = 0; - - /* Find the start of the next token. */ - z1 = zStr; - while( z2==0 ){ - char c = *z1; - switch( c ){ - case '\0': return 0; /* No more tokens here */ - case '\'': - case '"': - case '`': { - z2 = z1; - while( *++z2 && (*z2!=c || *++z2==c) ); - break; - } - case '[': - z2 = &z1[1]; - while( *z2 && z2[0]!=']' ) z2++; - if( *z2 ) z2++; - break; - - default: - if( sqlite3Fts3IsIdChar(*z1) ){ - z2 = &z1[1]; - while( sqlite3Fts3IsIdChar(*z2) ) z2++; - }else{ - z1++; - } - } - } - - *pn = (int)(z2-z1); - return z1; -} - -int sqlite3Fts3InitTokenizer( - Fts3Hash *pHash, /* Tokenizer hash table */ - const char *zArg, /* Tokenizer name */ - sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */ - char **pzErr /* OUT: Set to malloced error message */ -){ - int rc; - char *z = (char *)zArg; - int n = 0; - char *zCopy; - char *zEnd; /* Pointer to nul-term of zCopy */ - sqlite3_tokenizer_module *m; - - zCopy = sqlite3_mprintf("%s", zArg); - if( !zCopy ) return SQLITE_NOMEM; - zEnd = &zCopy[strlen(zCopy)]; - - z = (char *)sqlite3Fts3NextToken(zCopy, &n); - if( z==0 ){ - assert( n==0 ); - z = zCopy; - } - z[n] = '\0'; - sqlite3Fts3Dequote(z); - - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); - if( !m ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z); - rc = SQLITE_ERROR; - }else{ - char const **aArg = 0; - int iArg = 0; - z = &z[n+1]; - while( zxCreate(iArg, aArg, ppTok); - assert( rc!=SQLITE_OK || *ppTok ); - if( rc!=SQLITE_OK ){ - sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); - }else{ - (*ppTok)->pModule = m; - } - sqlite3_free((void *)aArg); - } - - sqlite3_free(zCopy); - return rc; -} - - -#ifdef SQLITE_TEST - -#if defined(INCLUDE_SQLITE_TCL_H) -# include "sqlite_tcl.h" -#else -# include "tcl.h" -#endif -#include - -/* -** Implementation of a special SQL scalar function for testing tokenizers -** designed to be used in concert with the Tcl testing framework. This -** function must be called with two or more arguments: -** -** SELECT (, ..., ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') -** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). -** -** The return value is a string that may be interpreted as a Tcl -** list. For each token in the , three elements are -** added to the returned list. The first is the token position, the -** second is the token text (folded, stemmed, etc.) and the third is the -** substring of associated with the token. For example, -** using the built-in "simple" tokenizer: -** -** SELECT fts_tokenizer_test('simple', 'I don't see how'); -** -** will return the string: -** -** "{0 i I 1 dont don't 2 see see 3 how how}" -** -*/ -static void testFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - sqlite3_tokenizer_module *p; - sqlite3_tokenizer *pTokenizer = 0; - sqlite3_tokenizer_cursor *pCsr = 0; - - const char *zErr = 0; - - const char *zName; - int nName; - const char *zInput; - int nInput; - - const char *azArg[64]; - - const char *zToken; - int nToken = 0; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int i; - - Tcl_Obj *pRet; - - if( argc<2 ){ - sqlite3_result_error(context, "insufficient arguments", -1); - return; - } - - nName = sqlite3_value_bytes(argv[0]); - zName = (const char *)sqlite3_value_text(argv[0]); - nInput = sqlite3_value_bytes(argv[argc-1]); - zInput = (const char *)sqlite3_value_text(argv[argc-1]); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - - if( !p ){ - char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr2, -1); - sqlite3_free(zErr2); - return; - } - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - - for(i=1; ixCreate(argc-2, azArg, &pTokenizer) ){ - zErr = "error in xCreate()"; - goto finish; - } - pTokenizer->pModule = p; - if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ - zErr = "error in xOpen()"; - goto finish; - } - - while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ - Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - zToken = &zInput[iStart]; - nToken = iEnd-iStart; - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - } - - if( SQLITE_OK!=p->xClose(pCsr) ){ - zErr = "error in xClose()"; - goto finish; - } - if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ - zErr = "error in xDestroy()"; - goto finish; - } - -finish: - if( zErr ){ - sqlite3_result_error(context, zErr, -1); - }else{ - sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); - } - Tcl_DecrRefCount(pRet); -} - -static -int registerTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module *p -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; - - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); - sqlite3_step(pStmt); - - return sqlite3_finalize(pStmt); -} - - -static -int queryTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - -void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); - -/* -** Implementation of the scalar function fts3_tokenizer_internal_test(). -** This function is used for testing only, it is not included in the -** build unless SQLITE_TEST is defined. -** -** The purpose of this is to test that the fts3_tokenizer() function -** can be used as designed by the C-code in the queryTokenizer and -** registerTokenizer() functions above. These two functions are repeated -** in the README.tokenizer file as an example, so it is important to -** test them. -** -** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar -** function with no arguments. An assert() will fail if a problem is -** detected. i.e.: -** -** SELECT fts3_tokenizer_internal_test(); -** -*/ -static void intTestFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int rc; - const sqlite3_tokenizer_module *p1; - const sqlite3_tokenizer_module *p2; - sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - /* Test the query function */ - sqlite3Fts3SimpleTokenizerModule(&p1); - rc = queryTokenizer(db, "simple", &p2); - assert( rc==SQLITE_OK ); - assert( p1==p2 ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_ERROR ); - assert( p2==0 ); - assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); - - /* Test the storage function */ - if( fts3TokenizerEnabled(context) ){ - rc = registerTokenizer(db, "nosuchtokenizer", p1); - assert( rc==SQLITE_OK ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_OK ); - assert( p2==p1 ); - } - - sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); -} - -#endif - -/* -** Set up SQL objects in database db used to access the contents of -** the hash table pointed to by argument pHash. The hash table must -** been initialized to use string keys, and to take a private copy -** of the key when a value is inserted. i.e. by a call similar to: -** -** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); -** -** This function adds a scalar function (see header comment above -** fts3TokenizerFunc() in this file for details) and, if ENABLE_TABLE is -** defined at compilation time, a temporary virtual table (see header -** comment above struct HashTableVtab) to the database schema. Both -** provide read/write access to the contents of *pHash. -** -** The third argument to this function, zName, is used as the name -** of both the scalar and, if created, the virtual table. -*/ -int sqlite3Fts3InitHashTable( - sqlite3 *db, - Fts3Hash *pHash, - const char *zName -){ - int rc = SQLITE_OK; - void *p = (void *)pHash; - const int any = SQLITE_ANY; - -#ifdef SQLITE_TEST - char *zTest = 0; - char *zTest2 = 0; - void *pdb = (void *)db; - zTest = sqlite3_mprintf("%s_test", zName); - zTest2 = sqlite3_mprintf("%s_internal_test", zName); - if( !zTest || !zTest2 ){ - rc = SQLITE_NOMEM; - } -#endif - - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 1, any, p, fts3TokenizerFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 2, any, p, fts3TokenizerFunc, 0, 0); - } -#ifdef SQLITE_TEST - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); - } -#endif - -#ifdef SQLITE_TEST - sqlite3_free(zTest); - sqlite3_free(zTest2); -#endif - - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.h b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.h deleted file mode 100644 index 4a40b2b3..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ -#include "sqlite3.h" - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0 or 1. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialized by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. *piStartOffset should be set to the index of the first - ** byte of the token in the input buffer. *piEndOffset should be set - ** to the index of the first byte just past the end of the token in - ** the input buffer. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); - - /*********************************************************************** - ** Methods below this point are only available if iVersion>=1. - */ - - /* - ** Configure the language id of a tokenizer cursor. - */ - int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -int fts3_global_term_cnt(int iTerm, int iCol); -int fts3_term_cnt(int iTerm, int iCol); - - -#endif /* _FTS3_TOKENIZER_H_ */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer1.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer1.c deleted file mode 100644 index deea06d9..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_tokenizer1.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** Implementation of the "simple" full-text-search tokenizer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include -#include -#include - -#include "fts3_tokenizer.h" - -typedef struct simple_tokenizer { - sqlite3_tokenizer base; - char delim[128]; /* flag ASCII delimiters */ -} simple_tokenizer; - -typedef struct simple_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *pInput; /* input we are tokenizing */ - int nBytes; /* size of the input */ - int iOffset; /* current position in pInput */ - int iToken; /* index of next token to be returned */ - char *pToken; /* storage for current token */ - int nTokenAllocated; /* space allocated to zToken buffer */ -} simple_tokenizer_cursor; - - -static int simpleDelim(simple_tokenizer *t, unsigned char c){ - return c<0x80 && t->delim[c]; -} -static int fts3_isalnum(int x){ - return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z'); -} - -/* -** Create a new tokenizer instance. -*/ -static int simpleCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - simple_tokenizer *t; - - t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - - /* TODO(shess) Delimiters need to remain the same from run to run, - ** else we need to reindex. One solution would be a meta-table to - ** track such information in the database, then we'd only want this - ** information on the initial create. - */ - if( argc>1 ){ - int i, n = (int)strlen(argv[1]); - for(i=0; i=0x80 ){ - sqlite3_free(t); - return SQLITE_ERROR; - } - t->delim[ch] = 1; - } - } else { - /* Mark non-alphanumeric ASCII characters as delimiters */ - int i; - for(i=1; i<0x80; i++){ - t->delim[i] = !fts3_isalnum(i) ? -1 : 0; - } - } - - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int simpleOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *pInput, int nBytes, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - simple_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->pInput = pInput; - if( pInput==0 ){ - c->nBytes = 0; - }else if( nBytes<0 ){ - c->nBytes = (int)strlen(pInput); - }else{ - c->nBytes = nBytes; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->pToken = NULL; /* no space allocated, yet. */ - c->nTokenAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - sqlite3_free(c->pToken); - sqlite3_free(c); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int simpleNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; - unsigned char *p = (unsigned char *)c->pInput; - - while( c->iOffsetnBytes ){ - int iStartOffset; - - /* Scan past delimiter characters */ - while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int i, n = c->iOffset-iStartOffset; - if( n>c->nTokenAllocated ){ - char *pNew; - c->nTokenAllocated = n+20; - pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->pToken = pNew; - } - for(i=0; ipToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch); - } - *ppToken = c->pToken; - *pnBytes = n; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module simpleTokenizerModule = { - 0, - simpleCreate, - simpleDestroy, - simpleOpen, - simpleClose, - simpleNext, - 0, -}; - -/* -** Allocate a new simple tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -void sqlite3Fts3SimpleTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &simpleTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode.c deleted file mode 100644 index b06d9921..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode.c +++ /dev/null @@ -1,396 +0,0 @@ -/* -** 2012 May 24 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** Implementation of the "unicode" full-text-search tokenizer. -*/ - -#ifndef SQLITE_DISABLE_FTS3_UNICODE - -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include -#include -#include - -#include "fts3_tokenizer.h" - -/* -** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied -** from the sqlite3 source file utf.c. If this file is compiled as part -** of the amalgamation, they are not required. -*/ -#ifndef SQLITE_AMALGAMATION - -static const unsigned char sqlite3Utf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - -#define READ_UTF8(zIn, zTerm, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ - c = (c<<6) + (0x3f & *(zIn++)); \ - } \ - if( c<0x80 \ - || (c&0xFFFFF800)==0xD800 \ - || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ - } - -#define WRITE_UTF8(zOut, c) { \ - if( c<0x00080 ){ \ - *zOut++ = (u8)(c&0xFF); \ - } \ - else if( c<0x00800 ){ \ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ - else if( c<0x10000 ){ \ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - }else{ \ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ -} - -#endif /* ifndef SQLITE_AMALGAMATION */ - -typedef struct unicode_tokenizer unicode_tokenizer; -typedef struct unicode_cursor unicode_cursor; - -struct unicode_tokenizer { - sqlite3_tokenizer base; - int eRemoveDiacritic; - int nException; - int *aiException; -}; - -struct unicode_cursor { - sqlite3_tokenizer_cursor base; - const unsigned char *aInput; /* Input text being tokenized */ - int nInput; /* Size of aInput[] in bytes */ - int iOff; /* Current offset within aInput[] */ - int iToken; /* Index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAlloc; /* space allocated at zToken */ -}; - - -/* -** Destroy a tokenizer allocated by unicodeCreate(). -*/ -static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){ - if( pTokenizer ){ - unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer; - sqlite3_free(p->aiException); - sqlite3_free(p); - } - return SQLITE_OK; -} - -/* -** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE -** statement has specified that the tokenizer for this table shall consider -** all characters in string zIn/nIn to be separators (if bAlnum==0) or -** token characters (if bAlnum==1). -** -** For each codepoint in the zIn/nIn string, this function checks if the -** sqlite3FtsUnicodeIsalnum() function already returns the desired result. -** If so, no action is taken. Otherwise, the codepoint is added to the -** unicode_tokenizer.aiException[] array. For the purposes of tokenization, -** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all -** codepoints in the aiException[] array. -** -** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() -** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. -** It is not possible to change the behavior of the tokenizer with respect -** to these codepoints. -*/ -static int unicodeAddExceptions( - unicode_tokenizer *p, /* Tokenizer to add exceptions to */ - int bAlnum, /* Replace Isalnum() return value with this */ - const char *zIn, /* Array of characters to make exceptions */ - int nIn /* Length of z in bytes */ -){ - const unsigned char *z = (const unsigned char *)zIn; - const unsigned char *zTerm = &z[nIn]; - unsigned int iCode; - int nEntry = 0; - - assert( bAlnum==0 || bAlnum==1 ); - - while( zaiException,(p->nException+nEntry)*sizeof(int)); - if( aNew==0 ) return SQLITE_NOMEM; - nNew = p->nException; - - z = (const unsigned char *)zIn; - while( zi; j--) aNew[j] = aNew[j-1]; - aNew[i] = (int)iCode; - nNew++; - } - } - p->aiException = aNew; - p->nException = nNew; - } - - return SQLITE_OK; -} - -/* -** Return true if the p->aiException[] array contains the value iCode. -*/ -static int unicodeIsException(unicode_tokenizer *p, int iCode){ - if( p->nException>0 ){ - int *a = p->aiException; - int iLo = 0; - int iHi = p->nException-1; - - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( iCode==a[iTest] ){ - return 1; - }else if( iCode>a[iTest] ){ - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - } - - return 0; -} - -/* -** Return true if, for the purposes of tokenization, codepoint iCode is -** considered a token character (not a separator). -*/ -static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){ - assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); - return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode); -} - -/* -** Create a new tokenizer instance. -*/ -static int unicodeCreate( - int nArg, /* Size of array argv[] */ - const char * const *azArg, /* Tokenizer creation arguments */ - sqlite3_tokenizer **pp /* OUT: New tokenizer handle */ -){ - unicode_tokenizer *pNew; /* New tokenizer object */ - int i; - int rc = SQLITE_OK; - - pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer)); - if( pNew==NULL ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(unicode_tokenizer)); - pNew->eRemoveDiacritic = 1; - - for(i=0; rc==SQLITE_OK && ieRemoveDiacritic = 1; - } - else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){ - pNew->eRemoveDiacritic = 0; - } - else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){ - pNew->eRemoveDiacritic = 2; - } - else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 1, &z[11], n-11); - } - else if( n>=11 && memcmp("separators=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 0, &z[11], n-11); - } - else{ - /* Unrecognized argument */ - rc = SQLITE_ERROR; - } - } - - if( rc!=SQLITE_OK ){ - unicodeDestroy((sqlite3_tokenizer *)pNew); - pNew = 0; - } - *pp = (sqlite3_tokenizer *)pNew; - return rc; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int unicodeOpen( - sqlite3_tokenizer *p, /* The tokenizer */ - const char *aInput, /* Input string */ - int nInput, /* Size of string aInput in bytes */ - sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */ -){ - unicode_cursor *pCsr; - - pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(unicode_cursor)); - - pCsr->aInput = (const unsigned char *)aInput; - if( aInput==0 ){ - pCsr->nInput = 0; - }else if( nInput<0 ){ - pCsr->nInput = (int)strlen(aInput); - }else{ - pCsr->nInput = nInput; - } - - *pp = &pCsr->base; - UNUSED_PARAMETER(p); - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){ - unicode_cursor *pCsr = (unicode_cursor *) pCursor; - sqlite3_free(pCsr->zToken); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int unicodeNext( - sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */ - const char **paToken, /* OUT: Token text */ - int *pnToken, /* OUT: Number of bytes at *paToken */ - int *piStart, /* OUT: Starting offset of token */ - int *piEnd, /* OUT: Ending offset of token */ - int *piPos /* OUT: Position integer of token */ -){ - unicode_cursor *pCsr = (unicode_cursor *)pC; - unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); - unsigned int iCode = 0; - char *zOut; - const unsigned char *z = &pCsr->aInput[pCsr->iOff]; - const unsigned char *zStart = z; - const unsigned char *zEnd; - const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; - - /* Scan past any delimiter characters before the start of the next token. - ** Return SQLITE_DONE early if this takes us all the way to the end of - ** the input. */ - while( z=zTerm ) return SQLITE_DONE; - - zOut = pCsr->zToken; - do { - int iOut; - - /* Grow the output buffer if required. */ - if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){ - char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64); - if( !zNew ) return SQLITE_NOMEM; - zOut = &zNew[zOut - pCsr->zToken]; - pCsr->zToken = zNew; - pCsr->nAlloc += 64; - } - - /* Write the folded case of the last character read to the output */ - zEnd = z; - iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic); - if( iOut ){ - WRITE_UTF8(zOut, iOut); - } - - /* If the cursor is not at EOF, read the next character */ - if( z>=zTerm ) break; - READ_UTF8(z, zTerm, iCode); - }while( unicodeIsAlnum(p, (int)iCode) - || sqlite3FtsUnicodeIsdiacritic((int)iCode) - ); - - /* Set the output variables and return. */ - pCsr->iOff = (int)(z - pCsr->aInput); - *paToken = pCsr->zToken; - *pnToken = (int)(zOut - pCsr->zToken); - *piStart = (int)(zStart - pCsr->aInput); - *piEnd = (int)(zEnd - pCsr->aInput); - *piPos = pCsr->iToken++; - return SQLITE_OK; -} - -/* -** Set *ppModule to a pointer to the sqlite3_tokenizer_module -** structure for the unicode tokenizer. -*/ -void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){ - static const sqlite3_tokenizer_module module = { - 0, - unicodeCreate, - unicodeDestroy, - unicodeOpen, - unicodeClose, - unicodeNext, - 0, - }; - *ppModule = &module; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ -#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode2.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode2.c deleted file mode 100644 index c5101624..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_unicode2.c +++ /dev/null @@ -1,383 +0,0 @@ -/* -** 2012-05-25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -*/ - -/* -** DO NOT EDIT THIS MACHINE GENERATED FILE. -*/ - -#ifndef SQLITE_DISABLE_FTS3_UNICODE -#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) - -#include - -/* -** Return true if the argument corresponds to a unicode codepoint -** classified as either a letter or a number. Otherwise false. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -int sqlite3FtsUnicodeIsalnum(int c){ - /* Each unsigned integer in the following array corresponds to a contiguous - ** range of unicode codepoints that are not either letters or numbers (i.e. - ** codepoints for which this function should return 0). - ** - ** The most significant 22 bits in each 32-bit value contain the first - ** codepoint in the range. The least significant 10 bits are used to store - ** the size of the range (always at least 1). In other words, the value - ** ((C<<22) + N) represents a range of N codepoints starting with codepoint - ** C. It is not possible to represent a range larger than 1023 codepoints - ** using this format. - */ - static const unsigned int aEntry[] = { - 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, - 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, - 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, - 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, - 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, - 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, - 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, - 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, - 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, - 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, - 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, - 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, - 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, - 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, - 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, - 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, - 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, - 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, - 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, - 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, - 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, - 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, - 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, - 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, - 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, - 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, - 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, - 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, - 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, - 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, - 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, - 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, - 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, - 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, - 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, - 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, - 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, - 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, - 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, - 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, - 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, - 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, - 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, - 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, - 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, - 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, - 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, - 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, - 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, - 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, - 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, - 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, - 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, - 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, - 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, - 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, - 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, - 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, - 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, - 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, - 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, - 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, - 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, - 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, - 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, - 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, - 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, - 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, - 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, - 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, - 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, - 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, - 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, - 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, - 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, - 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, - 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, - 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, - 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, - 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, - 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, - 0x380400F0, - }; - static const unsigned int aAscii[4] = { - 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, - }; - - if( (unsigned int)c<128 ){ - return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 ); - }else if( (unsigned int)c<(1<<22) ){ - unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; - int iRes = 0; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aEntry[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( aEntry[0]=aEntry[iRes] ); - return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); - } - return 1; -} - - -/* -** If the argument is a codepoint corresponding to a lowercase letter -** in the ASCII range with a diacritic added, return the codepoint -** of the ASCII letter only. For example, if passed 235 - "LATIN -** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER -** E"). The resuls of passing a codepoint that corresponds to an -** uppercase letter are undefined. -*/ -static int remove_diacritic(int c, int bComplex){ - unsigned short aDia[] = { - 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, - 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, - 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, - 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, - 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896, - 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106, - 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344, - 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198, - 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468, - 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704, - 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914, - 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218, - 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554, - 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766, - 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118, - 63182, 63242, 63274, 63310, 63368, 63390, - }; -#define HIBIT ((unsigned char)0x80) - unsigned char aChar[] = { - '\0', 'a', 'c', 'e', 'i', 'n', - 'o', 'u', 'y', 'y', 'a', 'c', - 'd', 'e', 'e', 'g', 'h', 'i', - 'j', 'k', 'l', 'n', 'o', 'r', - 's', 't', 'u', 'u', 'w', 'y', - 'z', 'o', 'u', 'a', 'i', 'o', - 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o', - 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a', - 'e', 'i', 'o', 'r', 'u', 's', - 't', 'h', 'a', 'e', 'o'|HIBIT, 'o', - 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', 'a', 'b', - 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT, - 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT, - 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n', - 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's', - 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w', - 'w', 'x', 'y', 'z', 'h', 't', - 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT, - 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT, - 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y', - }; - - unsigned int key = (((unsigned int)c)<<3) | 0x00000007; - int iRes = 0; - int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aDia[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( key>=aDia[iRes] ); - if( bComplex==0 && (aChar[iRes] & 0x80) ) return c; - return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F); -} - - -/* -** Return true if the argument interpreted as a unicode codepoint -** is a diacritical modifier character. -*/ -int sqlite3FtsUnicodeIsdiacritic(int c){ - unsigned int mask0 = 0x08029FDF; - unsigned int mask1 = 0x000361F8; - if( c<768 || c>817 ) return 0; - return (c < 768+32) ? - (mask0 & ((unsigned int)1 << (c-768))) : - (mask1 & ((unsigned int)1 << (c-768-32))); -} - - -/* -** Interpret the argument as a unicode codepoint. If the codepoint -** is an upper case character that has a lower case equivalent, -** return the codepoint corresponding to the lower case version. -** Otherwise, return a copy of the argument. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ - /* Each entry in the following array defines a rule for folding a range - ** of codepoints to lower case. The rule applies to a range of nRange - ** codepoints starting at codepoint iCode. - ** - ** If the least significant bit in flags is clear, then the rule applies - ** to all nRange codepoints (i.e. all nRange codepoints are upper case and - ** need to be folded). Or, if it is set, then the rule only applies to - ** every second codepoint in the range, starting with codepoint C. - ** - ** The 7 most significant bits in flags are an index into the aiOff[] - ** array. If a specific codepoint C does require folding, then its lower - ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF). - ** - ** The contents of this array are generated by parsing the CaseFolding.txt - ** file distributed as part of the "Unicode Character Database". See - ** http://www.unicode.org for details. - */ - static const struct TableEntry { - unsigned short iCode; - unsigned char flags; - unsigned char nRange; - } aEntry[] = { - {65, 14, 26}, {181, 64, 1}, {192, 14, 23}, - {216, 14, 7}, {256, 1, 48}, {306, 1, 6}, - {313, 1, 16}, {330, 1, 46}, {376, 116, 1}, - {377, 1, 6}, {383, 104, 1}, {385, 50, 1}, - {386, 1, 4}, {390, 44, 1}, {391, 0, 1}, - {393, 42, 2}, {395, 0, 1}, {398, 32, 1}, - {399, 38, 1}, {400, 40, 1}, {401, 0, 1}, - {403, 42, 1}, {404, 46, 1}, {406, 52, 1}, - {407, 48, 1}, {408, 0, 1}, {412, 52, 1}, - {413, 54, 1}, {415, 56, 1}, {416, 1, 6}, - {422, 60, 1}, {423, 0, 1}, {425, 60, 1}, - {428, 0, 1}, {430, 60, 1}, {431, 0, 1}, - {433, 58, 2}, {435, 1, 4}, {439, 62, 1}, - {440, 0, 1}, {444, 0, 1}, {452, 2, 1}, - {453, 0, 1}, {455, 2, 1}, {456, 0, 1}, - {458, 2, 1}, {459, 1, 18}, {478, 1, 18}, - {497, 2, 1}, {498, 1, 4}, {502, 122, 1}, - {503, 134, 1}, {504, 1, 40}, {544, 110, 1}, - {546, 1, 18}, {570, 70, 1}, {571, 0, 1}, - {573, 108, 1}, {574, 68, 1}, {577, 0, 1}, - {579, 106, 1}, {580, 28, 1}, {581, 30, 1}, - {582, 1, 10}, {837, 36, 1}, {880, 1, 4}, - {886, 0, 1}, {902, 18, 1}, {904, 16, 3}, - {908, 26, 1}, {910, 24, 2}, {913, 14, 17}, - {931, 14, 9}, {962, 0, 1}, {975, 4, 1}, - {976, 140, 1}, {977, 142, 1}, {981, 146, 1}, - {982, 144, 1}, {984, 1, 24}, {1008, 136, 1}, - {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1}, - {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1}, - {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32}, - {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1}, - {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38}, - {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1}, - {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1}, - {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6}, - {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6}, - {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8}, - {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2}, - {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1}, - {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2}, - {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2}, - {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2}, - {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1}, - {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16}, - {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47}, - {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1}, - {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1}, - {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1}, - {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2}, - {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, - {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, - {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, - {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, - {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, - {65313, 14, 26}, - }; - static const unsigned short aiOff[] = { - 1, 2, 8, 15, 16, 26, 28, 32, - 37, 38, 40, 48, 63, 64, 69, 71, - 79, 80, 116, 202, 203, 205, 206, 207, - 209, 210, 211, 213, 214, 217, 218, 219, - 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, - 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, - 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, - 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, - 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, - 65514, 65521, 65527, 65528, 65529, - }; - - int ret = c; - - assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); - - if( c<128 ){ - if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); - }else if( c<65536 ){ - const struct TableEntry *p; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - int iRes = -1; - - assert( c>aEntry[0].iCode ); - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - int cmp = (c - aEntry[iTest].iCode); - if( cmp>=0 ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - - assert( iRes>=0 && c>=aEntry[iRes].iCode ); - p = &aEntry[iRes]; - if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ - ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; - assert( ret>0 ); - } - - if( eRemoveDiacritic ){ - ret = remove_diacritic(ret, eRemoveDiacritic==2); - } - } - - else if( c>=66560 && c<66600 ){ - ret = c + 40; - } - - return ret; -} -#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ -#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_write.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_write.c deleted file mode 100644 index 031b7b35..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/fts3/fts3_write.c +++ /dev/null @@ -1,5709 +0,0 @@ -/* -** 2009 Oct 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file is part of the SQLite FTS3 extension module. Specifically, -** this file contains code to insert, update and delete rows from FTS3 -** tables. It also contains code to merge FTS3 b-tree segments. Some -** of the sub-routines used to merge segments are also used by the query -** code in fts3.c. -*/ - -#include "fts3Int.h" -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#include -#include -#include - - -#define FTS_MAX_APPENDABLE_HEIGHT 16 - -/* -** When full-text index nodes are loaded from disk, the buffer that they -** are loaded into has the following number of bytes of padding at the end -** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer -** of 920 bytes is allocated for it. -** -** This means that if we have a pointer into a buffer containing node data, -** it is always safe to read up to two varints from it without risking an -** overread, even if the node data is corrupted. -*/ -#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2) - -/* -** Under certain circumstances, b-tree nodes (doclists) can be loaded into -** memory incrementally instead of all at once. This can be a big performance -** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext() -** method before retrieving all query results (as may happen, for example, -** if a query has a LIMIT clause). -** -** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD -** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes. -** The code is written so that the hard lower-limit for each of these values -** is 1. Clearly such small values would be inefficient, but can be useful -** for testing purposes. -** -** If this module is built with SQLITE_TEST defined, these constants may -** be overridden at runtime for testing purposes. File fts3_test.c contains -** a Tcl interface to read and write the values. -*/ -#ifdef SQLITE_TEST -int test_fts3_node_chunksize = (4*1024); -int test_fts3_node_chunk_threshold = (4*1024)*4; -# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize -# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold -#else -# define FTS3_NODE_CHUNKSIZE (4*1024) -# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4) -#endif - -/* -** The two values that may be meaningfully bound to the :1 parameter in -** statements SQL_REPLACE_STAT and SQL_SELECT_STAT. -*/ -#define FTS_STAT_DOCTOTAL 0 -#define FTS_STAT_INCRMERGEHINT 1 -#define FTS_STAT_AUTOINCRMERGE 2 - -/* -** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic -** and incremental merge operation that takes place. This is used for -** debugging FTS only, it should not usually be turned on in production -** systems. -*/ -#ifdef FTS3_LOG_MERGES -static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){ - sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel); -} -#else -#define fts3LogMerge(x, y) -#endif - - -typedef struct PendingList PendingList; -typedef struct SegmentNode SegmentNode; -typedef struct SegmentWriter SegmentWriter; - -/* -** An instance of the following data structure is used to build doclists -** incrementally. See function fts3PendingListAppend() for details. -*/ -struct PendingList { - int nData; - char *aData; - int nSpace; - sqlite3_int64 iLastDocid; - sqlite3_int64 iLastCol; - sqlite3_int64 iLastPos; -}; - - -/* -** Each cursor has a (possibly empty) linked list of the following objects. -*/ -struct Fts3DeferredToken { - Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */ - int iCol; /* Column token must occur in */ - Fts3DeferredToken *pNext; /* Next in list of deferred tokens */ - PendingList *pList; /* Doclist is assembled here */ -}; - -/* -** An instance of this structure is used to iterate through the terms on -** a contiguous set of segment b-tree leaf nodes. Although the details of -** this structure are only manipulated by code in this file, opaque handles -** of type Fts3SegReader* are also used by code in fts3.c to iterate through -** terms when querying the full-text index. See functions: -** -** sqlite3Fts3SegReaderNew() -** sqlite3Fts3SegReaderFree() -** sqlite3Fts3SegReaderIterate() -** -** Methods used to manipulate Fts3SegReader structures: -** -** fts3SegReaderNext() -** fts3SegReaderFirstDocid() -** fts3SegReaderNextDocid() -*/ -struct Fts3SegReader { - int iIdx; /* Index within level, or 0x7FFFFFFF for PT */ - u8 bLookup; /* True for a lookup only */ - u8 rootOnly; /* True for a root-only reader */ - - sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */ - sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */ - sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */ - sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */ - - char *aNode; /* Pointer to node data (or NULL) */ - int nNode; /* Size of buffer at aNode (or 0) */ - int nPopulate; /* If >0, bytes of buffer aNode[] loaded */ - sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */ - - Fts3HashElem **ppNextElem; - - /* Variables set by fts3SegReaderNext(). These may be read directly - ** by the caller. They are valid from the time SegmentReaderNew() returns - ** until SegmentReaderNext() returns something other than SQLITE_OK - ** (i.e. SQLITE_DONE). - */ - int nTerm; /* Number of bytes in current term */ - char *zTerm; /* Pointer to current term */ - int nTermAlloc; /* Allocated size of zTerm buffer */ - char *aDoclist; /* Pointer to doclist of current entry */ - int nDoclist; /* Size of doclist in current entry */ - - /* The following variables are used by fts3SegReaderNextDocid() to iterate - ** through the current doclist (aDoclist/nDoclist). - */ - char *pOffsetList; - int nOffsetList; /* For descending pending seg-readers only */ - sqlite3_int64 iDocid; -}; - -#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0) -#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0) - -/* -** An instance of this structure is used to create a segment b-tree in the -** database. The internal details of this type are only accessed by the -** following functions: -** -** fts3SegWriterAdd() -** fts3SegWriterFlush() -** fts3SegWriterFree() -*/ -struct SegmentWriter { - SegmentNode *pTree; /* Pointer to interior tree structure */ - sqlite3_int64 iFirst; /* First slot in %_segments written */ - sqlite3_int64 iFree; /* Next free slot in %_segments */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nSize; /* Size of allocation at aData */ - int nData; /* Bytes of data in aData */ - char *aData; /* Pointer to block from malloc() */ - i64 nLeafData; /* Number of bytes of leaf data written */ -}; - -/* -** Type SegmentNode is used by the following three functions to create -** the interior part of the segment b+-tree structures (everything except -** the leaf nodes). These functions and type are only ever used by code -** within the fts3SegWriterXXX() family of functions described above. -** -** fts3NodeAddTerm() -** fts3NodeWrite() -** fts3NodeFree() -** -** When a b+tree is written to the database (either as a result of a merge -** or the pending-terms table being flushed), leaves are written into the -** database file as soon as they are completely populated. The interior of -** the tree is assembled in memory and written out only once all leaves have -** been populated and stored. This is Ok, as the b+-tree fanout is usually -** very large, meaning that the interior of the tree consumes relatively -** little memory. -*/ -struct SegmentNode { - SegmentNode *pParent; /* Parent node (or NULL for root node) */ - SegmentNode *pRight; /* Pointer to right-sibling */ - SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */ - int nEntry; /* Number of terms written to node so far */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nData; /* Bytes of valid data so far */ - char *aData; /* Node data */ -}; - -/* -** Valid values for the second argument to fts3SqlStmt(). -*/ -#define SQL_DELETE_CONTENT 0 -#define SQL_IS_EMPTY 1 -#define SQL_DELETE_ALL_CONTENT 2 -#define SQL_DELETE_ALL_SEGMENTS 3 -#define SQL_DELETE_ALL_SEGDIR 4 -#define SQL_DELETE_ALL_DOCSIZE 5 -#define SQL_DELETE_ALL_STAT 6 -#define SQL_SELECT_CONTENT_BY_ROWID 7 -#define SQL_NEXT_SEGMENT_INDEX 8 -#define SQL_INSERT_SEGMENTS 9 -#define SQL_NEXT_SEGMENTS_ID 10 -#define SQL_INSERT_SEGDIR 11 -#define SQL_SELECT_LEVEL 12 -#define SQL_SELECT_LEVEL_RANGE 13 -#define SQL_SELECT_LEVEL_COUNT 14 -#define SQL_SELECT_SEGDIR_MAX_LEVEL 15 -#define SQL_DELETE_SEGDIR_LEVEL 16 -#define SQL_DELETE_SEGMENTS_RANGE 17 -#define SQL_CONTENT_INSERT 18 -#define SQL_DELETE_DOCSIZE 19 -#define SQL_REPLACE_DOCSIZE 20 -#define SQL_SELECT_DOCSIZE 21 -#define SQL_SELECT_STAT 22 -#define SQL_REPLACE_STAT 23 - -#define SQL_SELECT_ALL_PREFIX_LEVEL 24 -#define SQL_DELETE_ALL_TERMS_SEGDIR 25 -#define SQL_DELETE_SEGDIR_RANGE 26 -#define SQL_SELECT_ALL_LANGID 27 -#define SQL_FIND_MERGE_LEVEL 28 -#define SQL_MAX_LEAF_NODE_ESTIMATE 29 -#define SQL_DELETE_SEGDIR_ENTRY 30 -#define SQL_SHIFT_SEGDIR_ENTRY 31 -#define SQL_SELECT_SEGDIR 32 -#define SQL_CHOMP_SEGDIR 33 -#define SQL_SEGMENT_IS_APPENDABLE 34 -#define SQL_SELECT_INDEXES 35 -#define SQL_SELECT_MXLEVEL 36 - -#define SQL_SELECT_LEVEL_RANGE2 37 -#define SQL_UPDATE_LEVEL_IDX 38 -#define SQL_UPDATE_LEVEL 39 - -/* -** This function is used to obtain an SQLite prepared statement handle -** for the statement identified by the second argument. If successful, -** *pp is set to the requested statement handle and SQLITE_OK returned. -** Otherwise, an SQLite error code is returned and *pp is set to 0. -** -** If argument apVal is not NULL, then it must point to an array with -** at least as many entries as the requested statement has bound -** parameters. The values are bound to the statements parameters before -** returning. -*/ -static int fts3SqlStmt( - Fts3Table *p, /* Virtual table handle */ - int eStmt, /* One of the SQL_XXX constants above */ - sqlite3_stmt **pp, /* OUT: Statement handle */ - sqlite3_value **apVal /* Values to bind to statement */ -){ - const char *azSql[] = { -/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", -/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", -/* 2 */ "DELETE FROM %Q.'%q_content'", -/* 3 */ "DELETE FROM %Q.'%q_segments'", -/* 4 */ "DELETE FROM %Q.'%q_segdir'", -/* 5 */ "DELETE FROM %Q.'%q_docsize'", -/* 6 */ "DELETE FROM %Q.'%q_stat'", -/* 7 */ "SELECT %s WHERE rowid=?", -/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", -/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", -/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", -/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", - - /* Return segments in order from oldest to newest.*/ -/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", -/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?" - "ORDER BY level DESC, idx ASC", - -/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", -/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", - -/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", -/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", -/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", -/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", -/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", -/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", -/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", -/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", -/* 24 */ "", -/* 25 */ "", - -/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", - -/* This statement is used to determine which level to read the input from -** when performing an incremental merge. It returns the absolute level number -** of the oldest level in the db that contains at least ? segments. Or, -** if no level in the FTS index contains more than ? segments, the statement -** returns zero rows. */ -/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' " - " GROUP BY level HAVING cnt>=?" - " ORDER BY (level %% 1024) ASC LIMIT 1", - -/* Estimate the upper limit on the number of leaf nodes in a new segment -** created by merging the oldest :2 segments from absolute level :1. See -** function sqlite3Fts3Incrmerge() for details. */ -/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) " - " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?", - -/* SQL_DELETE_SEGDIR_ENTRY -** Delete the %_segdir entry on absolute level :1 with index :2. */ -/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_SHIFT_SEGDIR_ENTRY -** Modify the idx value for the segment with idx=:3 on absolute level :2 -** to :1. */ -/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", - -/* SQL_SELECT_SEGDIR -** Read a single entry from the %_segdir table. The entry from absolute -** level :1 with index value :2. */ -/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_CHOMP_SEGDIR -** Update the start_block (:1) and root (:2) fields of the %_segdir -** entry located on absolute level :3 with index :4. */ -/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?" - "WHERE level = ? AND idx = ?", - -/* SQL_SEGMENT_IS_APPENDABLE -** Return a single row if the segment with end_block=? is appendable. Or -** no rows otherwise. */ -/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL", - -/* SQL_SELECT_INDEXES -** Return the list of valid segment indexes for absolute level ? */ -/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC", - -/* SQL_SELECT_MXLEVEL -** Return the largest relative level in the FTS index or indexes. */ -/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'", - - /* Return segments in order from oldest to newest.*/ -/* 37 */ "SELECT level, idx, end_block " - "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? " - "ORDER BY level DESC, idx ASC", - - /* Update statements used while promoting segments */ -/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? " - "WHERE level=? AND idx=?", -/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1" - - }; - int rc = SQLITE_OK; - sqlite3_stmt *pStmt; - - assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); - assert( eStmt=0 ); - - pStmt = p->aStmt[eStmt]; - if( !pStmt ){ - int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB; - char *zSql; - if( eStmt==SQL_CONTENT_INSERT ){ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); - }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - f &= ~SQLITE_PREPARE_NO_VTAB; - zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); - }else{ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); - } - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL); - sqlite3_free(zSql); - assert( rc==SQLITE_OK || pStmt==0 ); - p->aStmt[eStmt] = pStmt; - } - } - if( apVal ){ - int i; - int nParam = sqlite3_bind_parameter_count(pStmt); - for(i=0; rc==SQLITE_OK && inPendingData==0 ){ - sqlite3_stmt *pStmt; - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_null(pStmt, 1); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - } - } - - return rc; -} - -/* -** FTS maintains a separate indexes for each language-id (a 32-bit integer). -** Within each language id, a separate index is maintained to store the -** document terms, and each configured prefix size (configured the FTS -** "prefix=" option). And each index consists of multiple levels ("relative -** levels"). -** -** All three of these values (the language id, the specific index and the -** level within the index) are encoded in 64-bit integer values stored -** in the %_segdir table on disk. This function is used to convert three -** separate component values into the single 64-bit integer value that -** can be used to query the %_segdir table. -** -** Specifically, each language-id/index combination is allocated 1024 -** 64-bit integer level values ("absolute levels"). The main terms index -** for language-id 0 is allocate values 0-1023. The first prefix index -** (if any) for language-id 0 is allocated values 1024-2047. And so on. -** Language 1 indexes are allocated immediately following language 0. -** -** So, for a system with nPrefix prefix indexes configured, the block of -** absolute levels that corresponds to language-id iLangid and index -** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024). -*/ -static sqlite3_int64 getAbsoluteLevel( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index in p->aIndex[] */ - int iLevel /* Level of segments */ -){ - sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */ - assert_fts3_nc( iLangid>=0 ); - assert( p->nIndex>0 ); - assert( iIndex>=0 && iIndexnIndex ); - - iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL; - return iBase + iLevel; -} - -/* -** Set *ppStmt to a statement handle that may be used to iterate through -** all rows in the %_segdir table, from oldest to newest. If successful, -** return SQLITE_OK. If an error occurs while preparing the statement, -** return an SQLite error code. -** -** There is only ever one instance of this SQL statement compiled for -** each FTS3 table. -** -** The statement returns the following columns from the %_segdir table: -** -** 0: idx -** 1: start_block -** 2: leaves_end_block -** 3: end_block -** 4: root -*/ -int sqlite3Fts3AllSegdirs( - Fts3Table *p, /* FTS3 table */ - int iLangid, /* Language being queried */ - int iIndex, /* Index for p->aIndex[] */ - int iLevel, /* Level to select (relative level) */ - sqlite3_stmt **ppStmt /* OUT: Compiled statement */ -){ - int rc; - sqlite3_stmt *pStmt = 0; - - assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 ); - assert( iLevel=0 && iIndexnIndex ); - - if( iLevel<0 ){ - /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); - } - } - *ppStmt = pStmt; - return rc; -} - - -/* -** Append a single varint to a PendingList buffer. SQLITE_OK is returned -** if successful, or an SQLite error code otherwise. -** -** This function also serves to allocate the PendingList structure itself. -** For example, to create a new PendingList structure containing two -** varints: -** -** PendingList *p = 0; -** fts3PendingListAppendVarint(&p, 1); -** fts3PendingListAppendVarint(&p, 2); -*/ -static int fts3PendingListAppendVarint( - PendingList **pp, /* IN/OUT: Pointer to PendingList struct */ - sqlite3_int64 i /* Value to append to data */ -){ - PendingList *p = *pp; - - /* Allocate or grow the PendingList as required. */ - if( !p ){ - p = sqlite3_malloc(sizeof(*p) + 100); - if( !p ){ - return SQLITE_NOMEM; - } - p->nSpace = 100; - p->aData = (char *)&p[1]; - p->nData = 0; - } - else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - int nNew = p->nSpace * 2; - p = sqlite3_realloc(p, sizeof(*p) + nNew); - if( !p ){ - sqlite3_free(*pp); - *pp = 0; - return SQLITE_NOMEM; - } - p->nSpace = nNew; - p->aData = (char *)&p[1]; - } - - /* Append the new serialized varint to the end of the list. */ - p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i); - p->aData[p->nData] = '\0'; - *pp = p; - return SQLITE_OK; -} - -/* -** Add a docid/column/position entry to a PendingList structure. Non-zero -** is returned if the structure is sqlite3_realloced as part of adding -** the entry. Otherwise, zero. -** -** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning. -** Zero is always returned in this case. Otherwise, if no OOM error occurs, -** it is set to SQLITE_OK. -*/ -static int fts3PendingListAppend( - PendingList **pp, /* IN/OUT: PendingList structure */ - sqlite3_int64 iDocid, /* Docid for entry to add */ - sqlite3_int64 iCol, /* Column for entry to add */ - sqlite3_int64 iPos, /* Position of term for entry to add */ - int *pRc /* OUT: Return code */ -){ - PendingList *p = *pp; - int rc = SQLITE_OK; - - assert( !p || p->iLastDocid<=iDocid ); - - if( !p || p->iLastDocid!=iDocid ){ - sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0); - if( p ){ - assert( p->nDatanSpace ); - assert( p->aData[p->nData]==0 ); - p->nData++; - } - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){ - goto pendinglistappend_out; - } - p->iLastCol = -1; - p->iLastPos = 0; - p->iLastDocid = iDocid; - } - if( iCol>0 && p->iLastCol!=iCol ){ - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1)) - || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol)) - ){ - goto pendinglistappend_out; - } - p->iLastCol = iCol; - p->iLastPos = 0; - } - if( iCol>=0 ){ - assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); - rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); - if( rc==SQLITE_OK ){ - p->iLastPos = iPos; - } - } - - pendinglistappend_out: - *pRc = rc; - if( p!=*pp ){ - *pp = p; - return 1; - } - return 0; -} - -/* -** Free a PendingList object allocated by fts3PendingListAppend(). -*/ -static void fts3PendingListDelete(PendingList *pList){ - sqlite3_free(pList); -} - -/* -** Add an entry to one of the pending-terms hash tables. -*/ -static int fts3PendingTermsAddOne( - Fts3Table *p, - int iCol, - int iPos, - Fts3Hash *pHash, /* Pending terms hash table to add entry to */ - const char *zToken, - int nToken -){ - PendingList *pList; - int rc = SQLITE_OK; - - pList = (PendingList *)fts3HashFind(pHash, zToken, nToken); - if( pList ){ - p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); - } - if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ - if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ - /* Malloc failed while inserting the new entry. This can only - ** happen if there was no previous entry for this token. - */ - assert( 0==fts3HashFind(pHash, zToken, nToken) ); - sqlite3_free(pList); - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK ){ - p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); - } - return rc; -} - -/* -** Tokenize the nul-terminated string zText and add all tokens to the -** pending-terms hash-table. The docid used is that currently stored in -** p->iPrevDocid, and the column is specified by argument iCol. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3PendingTermsAdd( - Fts3Table *p, /* Table into which text will be inserted */ - int iLangid, /* Language id to use */ - const char *zText, /* Text of document to be inserted */ - int iCol, /* Column into which text is being inserted */ - u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */ -){ - int rc; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int nWord = 0; - - char const *zToken; - int nToken = 0; - - sqlite3_tokenizer *pTokenizer = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr; - int (*xNext)(sqlite3_tokenizer_cursor *pCursor, - const char**,int*,int*,int*,int*); - - assert( pTokenizer && pModule ); - - /* If the user has inserted a NULL value, this function may be called with - ** zText==0. In this case, add zero token entries to the hash table and - ** return early. */ - if( zText==0 ){ - *pnWord = 0; - return SQLITE_OK; - } - - rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); - if( rc!=SQLITE_OK ){ - return rc; - } - - xNext = pModule->xNext; - while( SQLITE_OK==rc - && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) - ){ - int i; - if( iPos>=nWord ) nWord = iPos+1; - - /* Positions cannot be negative; we use -1 as a terminator internally. - ** Tokens must have a non-zero length. - */ - if( iPos<0 || !zToken || nToken<=0 ){ - rc = SQLITE_ERROR; - break; - } - - /* Add the term to the terms index */ - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken - ); - - /* Add the term to each of the prefix indexes that it is not too - ** short for. */ - for(i=1; rc==SQLITE_OK && inIndex; i++){ - struct Fts3Index *pIndex = &p->aIndex[i]; - if( nTokennPrefix ) continue; - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix - ); - } - } - - pModule->xClose(pCsr); - *pnWord += nWord; - return (rc==SQLITE_DONE ? SQLITE_OK : rc); -} - -/* -** Calling this function indicates that subsequent calls to -** fts3PendingTermsAdd() are to add term/position-list pairs for the -** contents of the document with docid iDocid. -*/ -static int fts3PendingTermsDocid( - Fts3Table *p, /* Full-text table handle */ - int bDelete, /* True if this op is a delete */ - int iLangid, /* Language id of row being written */ - sqlite_int64 iDocid /* Docid of row being written */ -){ - assert( iLangid>=0 ); - assert( bDelete==1 || bDelete==0 ); - - /* TODO(shess) Explore whether partially flushing the buffer on - ** forced-flush would provide better performance. I suspect that if - ** we ordered the doclists by size and flushed the largest until the - ** buffer was half empty, that would let the less frequent terms - ** generate longer doclists. - */ - if( iDocidiPrevDocid - || (iDocid==p->iPrevDocid && p->bPrevDelete==0) - || p->iPrevLangid!=iLangid - || p->nPendingData>p->nMaxPendingData - ){ - int rc = sqlite3Fts3PendingTermsFlush(p); - if( rc!=SQLITE_OK ) return rc; - } - p->iPrevDocid = iDocid; - p->iPrevLangid = iLangid; - p->bPrevDelete = bDelete; - return SQLITE_OK; -} - -/* -** Discard the contents of the pending-terms hash tables. -*/ -void sqlite3Fts3PendingTermsClear(Fts3Table *p){ - int i; - for(i=0; inIndex; i++){ - Fts3HashElem *pElem; - Fts3Hash *pHash = &p->aIndex[i].hPending; - for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){ - PendingList *pList = (PendingList *)fts3HashData(pElem); - fts3PendingListDelete(pList); - } - fts3HashClear(pHash); - } - p->nPendingData = 0; -} - -/* -** This function is called by the xUpdate() method as part of an INSERT -** operation. It adds entries for each term in the new record to the -** pendingTerms hash table. -** -** Argument apVal is the same as the similarly named argument passed to -** fts3InsertData(). Parameter iDocid is the docid of the new row. -*/ -static int fts3InsertTerms( - Fts3Table *p, - int iLangid, - sqlite3_value **apVal, - u32 *aSz -){ - int i; /* Iterator variable */ - for(i=2; inColumn+2; i++){ - int iCol = i-2; - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_value_text(apVal[i]); - int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]); - if( rc!=SQLITE_OK ){ - return rc; - } - aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); - } - } - return SQLITE_OK; -} - -/* -** This function is called by the xUpdate() method for an INSERT operation. -** The apVal parameter is passed a copy of the apVal argument passed by -** SQLite to the xUpdate() method. i.e: -** -** apVal[0] Not used for INSERT. -** apVal[1] rowid -** apVal[2] Left-most user-defined column -** ... -** apVal[p->nColumn+1] Right-most user-defined column -** apVal[p->nColumn+2] Hidden column with same name as table -** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) -** apVal[p->nColumn+4] Hidden languageid column -*/ -static int fts3InsertData( - Fts3Table *p, /* Full-text table */ - sqlite3_value **apVal, /* Array of values to insert */ - sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ -){ - int rc; /* Return code */ - sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ - - if( p->zContentTbl ){ - sqlite3_value *pRowid = apVal[p->nColumn+3]; - if( sqlite3_value_type(pRowid)==SQLITE_NULL ){ - pRowid = apVal[1]; - } - if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){ - return SQLITE_CONSTRAINT; - } - *piDocid = sqlite3_value_int64(pRowid); - return SQLITE_OK; - } - - /* Locate the statement handle used to insert data into the %_content - ** table. The SQL for this statement is: - ** - ** INSERT INTO %_content VALUES(?, ?, ?, ...) - ** - ** The statement features N '?' variables, where N is the number of user - ** defined columns in the FTS3 table, plus one for the docid field. - */ - rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); - if( rc==SQLITE_OK && p->zLanguageid ){ - rc = sqlite3_bind_int( - pContentInsert, p->nColumn+2, - sqlite3_value_int(apVal[p->nColumn+4]) - ); - } - if( rc!=SQLITE_OK ) return rc; - - /* There is a quirk here. The users INSERT statement may have specified - ** a value for the "rowid" field, for the "docid" field, or for both. - ** Which is a problem, since "rowid" and "docid" are aliases for the - ** same value. For example: - ** - ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); - ** - ** In FTS3, this is an error. It is an error to specify non-NULL values - ** for both docid and some other rowid alias. - */ - if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ - if( SQLITE_NULL==sqlite3_value_type(apVal[0]) - && SQLITE_NULL!=sqlite3_value_type(apVal[1]) - ){ - /* A rowid/docid conflict. */ - return SQLITE_ERROR; - } - rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); - if( rc!=SQLITE_OK ) return rc; - } - - /* Execute the statement to insert the record. Set *piDocid to the - ** new docid value. - */ - sqlite3_step(pContentInsert); - rc = sqlite3_reset(pContentInsert); - - *piDocid = sqlite3_last_insert_rowid(p->db); - return rc; -} - - - -/* -** Remove all data from the FTS3 table. Clear the hash table containing -** pending terms. -*/ -static int fts3DeleteAll(Fts3Table *p, int bContent){ - int rc = SQLITE_OK; /* Return code */ - - /* Discard the contents of the pending-terms hash table. */ - sqlite3Fts3PendingTermsClear(p); - - /* Delete everything from the shadow tables. Except, leave %_content as - ** is if bContent is false. */ - assert( p->zContentTbl==0 || bContent==0 ); - if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); - } - if( p->bHasStat ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); - } - return rc; -} - -/* -** -*/ -static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ - int iLangid = 0; - if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); - return iLangid; -} - -/* -** The first element in the apVal[] array is assumed to contain the docid -** (an integer) of a row about to be deleted. Remove all terms from the -** full-text index. -*/ -static void fts3DeleteTerms( - int *pRC, /* Result code */ - Fts3Table *p, /* The FTS table to delete from */ - sqlite3_value *pRowid, /* The docid to be deleted */ - u32 *aSz, /* Sizes of deleted document written here */ - int *pbFound /* OUT: Set to true if row really does exist */ -){ - int rc; - sqlite3_stmt *pSelect; - - assert( *pbFound==0 ); - if( *pRC ) return; - rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - int i; - int iLangid = langidFromSelect(p, pSelect); - i64 iDocid = sqlite3_column_int64(pSelect, 0); - rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); - for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ - int iCol = i-1; - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pSelect, i); - rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]); - aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); - } - } - if( rc!=SQLITE_OK ){ - sqlite3_reset(pSelect); - *pRC = rc; - return; - } - *pbFound = 1; - } - rc = sqlite3_reset(pSelect); - }else{ - sqlite3_reset(pSelect); - } - *pRC = rc; -} - -/* -** Forward declaration to account for the circular dependency between -** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). -*/ -static int fts3SegmentMerge(Fts3Table *, int, int, int); - -/* -** This function allocates a new level iLevel index in the segdir table. -** Usually, indexes are allocated within a level sequentially starting -** with 0, so the allocated index is one greater than the value returned -** by: -** -** SELECT max(idx) FROM %_segdir WHERE level = :iLevel -** -** However, if there are already FTS3_MERGE_COUNT indexes at the requested -** level, they are merged into a single level (iLevel+1) segment and the -** allocated index is 0. -** -** If successful, *piIdx is set to the allocated index slot and SQLITE_OK -** returned. Otherwise, an SQLite error code is returned. -*/ -static int fts3AllocateSegdirIdx( - Fts3Table *p, - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, - int *piIdx -){ - int rc; /* Return Code */ - sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ - int iNext = 0; /* Result of query pNextIdx */ - - assert( iLangid>=0 ); - assert( p->nIndex>=1 ); - - /* Set variable iNext to the next available segdir index at level iLevel. */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ - iNext = sqlite3_column_int(pNextIdx, 0); - } - rc = sqlite3_reset(pNextIdx); - } - - if( rc==SQLITE_OK ){ - /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already - ** full, merge all segments in level iLevel into a single iLevel+1 - ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, - ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. - */ - if( iNext>=FTS3_MERGE_COUNT ){ - fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); - rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); - *piIdx = 0; - }else{ - *piIdx = iNext; - } - } - - return rc; -} - -/* -** The %_segments table is declared as follows: -** -** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB) -** -** This function reads data from a single row of the %_segments table. The -** specific row is identified by the iBlockid parameter. If paBlob is not -** NULL, then a buffer is allocated using sqlite3_malloc() and populated -** with the contents of the blob stored in the "block" column of the -** identified table row is. Whether or not paBlob is NULL, *pnBlob is set -** to the size of the blob in bytes before returning. -** -** If an error occurs, or the table does not contain the specified row, -** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If -** paBlob is non-NULL, then it is the responsibility of the caller to -** eventually free the returned buffer. -** -** This function may leave an open sqlite3_blob* handle in the -** Fts3Table.pSegments variable. This handle is reused by subsequent calls -** to this function. The handle may be closed by calling the -** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy -** performance improvement, but the blob handle should always be closed -** before control is returned to the user (to prevent a lock being held -** on the database file for longer than necessary). Thus, any virtual table -** method (xFilter etc.) that may directly or indirectly call this function -** must call sqlite3Fts3SegmentsClose() before returning. -*/ -int sqlite3Fts3ReadBlock( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */ - char **paBlob, /* OUT: Blob data in malloc'd buffer */ - int *pnBlob, /* OUT: Size of blob data */ - int *pnLoad /* OUT: Bytes actually loaded */ -){ - int rc; /* Return code */ - - /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */ - assert( pnBlob ); - - if( p->pSegments ){ - rc = sqlite3_blob_reopen(p->pSegments, iBlockid); - }else{ - if( 0==p->zSegmentsTbl ){ - p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName); - if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM; - } - rc = sqlite3_blob_open( - p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments - ); - } - - if( rc==SQLITE_OK ){ - int nByte = sqlite3_blob_bytes(p->pSegments); - *pnBlob = nByte; - if( paBlob ){ - char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING); - if( !aByte ){ - rc = SQLITE_NOMEM; - }else{ - if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){ - nByte = FTS3_NODE_CHUNKSIZE; - *pnLoad = nByte; - } - rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0); - memset(&aByte[nByte], 0, FTS3_NODE_PADDING); - if( rc!=SQLITE_OK ){ - sqlite3_free(aByte); - aByte = 0; - } - } - *paBlob = aByte; - } - } - - return rc; -} - -/* -** Close the blob handle at p->pSegments, if it is open. See comments above -** the sqlite3Fts3ReadBlock() function for details. -*/ -void sqlite3Fts3SegmentsClose(Fts3Table *p){ - sqlite3_blob_close(p->pSegments); - p->pSegments = 0; -} - -static int fts3SegReaderIncrRead(Fts3SegReader *pReader){ - int nRead; /* Number of bytes to read */ - int rc; /* Return code */ - - nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE); - rc = sqlite3_blob_read( - pReader->pBlob, - &pReader->aNode[pReader->nPopulate], - nRead, - pReader->nPopulate - ); - - if( rc==SQLITE_OK ){ - pReader->nPopulate += nRead; - memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING); - if( pReader->nPopulate==pReader->nNode ){ - sqlite3_blob_close(pReader->pBlob); - pReader->pBlob = 0; - pReader->nPopulate = 0; - } - } - return rc; -} - -static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){ - int rc = SQLITE_OK; - assert( !pReader->pBlob - || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode]) - ); - while( pReader->pBlob && rc==SQLITE_OK - && (pFrom - pReader->aNode + nByte)>pReader->nPopulate - ){ - rc = fts3SegReaderIncrRead(pReader); - } - return rc; -} - -/* -** Set an Fts3SegReader cursor to point at EOF. -*/ -static void fts3SegReaderSetEof(Fts3SegReader *pSeg){ - if( !fts3SegReaderIsRootOnly(pSeg) ){ - sqlite3_free(pSeg->aNode); - sqlite3_blob_close(pSeg->pBlob); - pSeg->pBlob = 0; - } - pSeg->aNode = 0; -} - -/* -** Move the iterator passed as the first argument to the next term in the -** segment. If successful, SQLITE_OK is returned. If there is no next term, -** SQLITE_DONE. Otherwise, an SQLite error code. -*/ -static int fts3SegReaderNext( - Fts3Table *p, - Fts3SegReader *pReader, - int bIncr -){ - int rc; /* Return code of various sub-routines */ - char *pNext; /* Cursor variable */ - int nPrefix; /* Number of bytes in term prefix */ - int nSuffix; /* Number of bytes in term suffix */ - - if( !pReader->aDoclist ){ - pNext = pReader->aNode; - }else{ - pNext = &pReader->aDoclist[pReader->nDoclist]; - } - - if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ - - if( fts3SegReaderIsPending(pReader) ){ - Fts3HashElem *pElem = *(pReader->ppNextElem); - sqlite3_free(pReader->aNode); - pReader->aNode = 0; - if( pElem ){ - char *aCopy; - PendingList *pList = (PendingList *)fts3HashData(pElem); - int nCopy = pList->nData+1; - pReader->zTerm = (char *)fts3HashKey(pElem); - pReader->nTerm = fts3HashKeysize(pElem); - aCopy = (char*)sqlite3_malloc(nCopy); - if( !aCopy ) return SQLITE_NOMEM; - memcpy(aCopy, pList->aData, nCopy); - pReader->nNode = pReader->nDoclist = nCopy; - pReader->aNode = pReader->aDoclist = aCopy; - pReader->ppNextElem++; - assert( pReader->aNode ); - } - return SQLITE_OK; - } - - fts3SegReaderSetEof(pReader); - - /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf - ** blocks have already been traversed. */ - assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock ); - if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){ - return SQLITE_OK; - } - - rc = sqlite3Fts3ReadBlock( - p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, - (bIncr ? &pReader->nPopulate : 0) - ); - if( rc!=SQLITE_OK ) return rc; - assert( pReader->pBlob==0 ); - if( bIncr && pReader->nPopulatenNode ){ - pReader->pBlob = p->pSegments; - p->pSegments = 0; - } - pNext = pReader->aNode; - } - - assert( !fts3SegReaderIsPending(pReader) ); - - rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2); - if( rc!=SQLITE_OK ) return rc; - - /* Because of the FTS3_NODE_PADDING bytes of padding, the following is - ** safe (no risk of overread) even if the node data is corrupted. */ - pNext += fts3GetVarint32(pNext, &nPrefix); - pNext += fts3GetVarint32(pNext, &nSuffix); - if( nSuffix<=0 - || (&pReader->aNode[pReader->nNode] - pNext)pReader->nTermAlloc - ){ - return FTS_CORRUPT_VTAB; - } - - /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are - ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer - ** overflow - hence the (i64) casts. */ - if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){ - i64 nNew = ((i64)nPrefix+nSuffix)*2; - char *zNew = sqlite3_realloc64(pReader->zTerm, nNew); - if( !zNew ){ - return SQLITE_NOMEM; - } - pReader->zTerm = zNew; - pReader->nTermAlloc = nNew; - } - - rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX); - if( rc!=SQLITE_OK ) return rc; - - memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix); - pReader->nTerm = nPrefix+nSuffix; - pNext += nSuffix; - pNext += fts3GetVarint32(pNext, &pReader->nDoclist); - pReader->aDoclist = pNext; - pReader->pOffsetList = 0; - - /* Check that the doclist does not appear to extend past the end of the - ** b-tree node. And that the final byte of the doclist is 0x00. If either - ** of these statements is untrue, then the data structure is corrupt. - */ - if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode) - || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) - ){ - return FTS_CORRUPT_VTAB; - } - return SQLITE_OK; -} - -/* -** Set the SegReader to point to the first docid in the doclist associated -** with the current term. -*/ -static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){ - int rc = SQLITE_OK; - assert( pReader->aDoclist ); - assert( !pReader->pOffsetList ); - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - u8 bEof = 0; - pReader->iDocid = 0; - pReader->nOffsetList = 0; - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, - &pReader->iDocid, &pReader->nOffsetList, &bEof - ); - }else{ - rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid); - pReader->pOffsetList = &pReader->aDoclist[n]; - } - } - return rc; -} - -/* -** Advance the SegReader to point to the next docid in the doclist -** associated with the current term. -** -** If arguments ppOffsetList and pnOffsetList are not NULL, then -** *ppOffsetList is set to point to the first column-offset list -** in the doclist entry (i.e. immediately past the docid varint). -** *pnOffsetList is set to the length of the set of column-offset -** lists, not including the nul-terminator byte. For example: -*/ -static int fts3SegReaderNextDocid( - Fts3Table *pTab, - Fts3SegReader *pReader, /* Reader to advance to next docid */ - char **ppOffsetList, /* OUT: Pointer to current position-list */ - int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */ -){ - int rc = SQLITE_OK; - char *p = pReader->pOffsetList; - char c = 0; - - assert( p ); - - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - /* A pending-terms seg-reader for an FTS4 table that uses order=desc. - ** Pending-terms doclists are always built up in ascending order, so - ** we have to iterate through them backwards here. */ - u8 bEof = 0; - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = pReader->nOffsetList - 1; - } - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid, - &pReader->nOffsetList, &bEof - ); - if( bEof ){ - pReader->pOffsetList = 0; - }else{ - pReader->pOffsetList = p; - } - }else{ - char *pEnd = &pReader->aDoclist[pReader->nDoclist]; - - /* Pointer p currently points at the first byte of an offset list. The - ** following block advances it to point one byte past the end of - ** the same offset list. */ - while( 1 ){ - - /* The following line of code (and the "p++" below the while() loop) is - ** normally all that is required to move pointer p to the desired - ** position. The exception is if this node is being loaded from disk - ** incrementally and pointer "p" now points to the first byte past - ** the populated part of pReader->aNode[]. - */ - while( *p | c ) c = *p++ & 0x80; - assert( *p==0 ); - - if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break; - rc = fts3SegReaderIncrRead(pReader); - if( rc!=SQLITE_OK ) return rc; - } - p++; - - /* If required, populate the output variables with a pointer to and the - ** size of the previous offset-list. - */ - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = (int)(p - pReader->pOffsetList - 1); - } - - /* List may have been edited in place by fts3EvalNearTrim() */ - while( p=pEnd ){ - pReader->pOffsetList = 0; - }else{ - rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - sqlite3_int64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta); - if( pTab->bDescIdx ){ - pReader->iDocid -= iDelta; - }else{ - pReader->iDocid += iDelta; - } - } - } - } - - return SQLITE_OK; -} - - -int sqlite3Fts3MsrOvfl( - Fts3Cursor *pCsr, - Fts3MultiSegReader *pMsr, - int *pnOvfl -){ - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - int nOvfl = 0; - int ii; - int rc = SQLITE_OK; - int pgsz = p->nPgsz; - - assert( p->bFts4 ); - assert( pgsz>0 ); - - for(ii=0; rc==SQLITE_OK && iinSegment; ii++){ - Fts3SegReader *pReader = pMsr->apSegment[ii]; - if( !fts3SegReaderIsPending(pReader) - && !fts3SegReaderIsRootOnly(pReader) - ){ - sqlite3_int64 jj; - for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){ - int nBlob; - rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0); - if( rc!=SQLITE_OK ) break; - if( (nBlob+35)>pgsz ){ - nOvfl += (nBlob + 34)/pgsz; - } - } - } - } - *pnOvfl = nOvfl; - return rc; -} - -/* -** Free all allocations associated with the iterator passed as the -** second argument. -*/ -void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ - if( pReader ){ - if( !fts3SegReaderIsPending(pReader) ){ - sqlite3_free(pReader->zTerm); - } - if( !fts3SegReaderIsRootOnly(pReader) ){ - sqlite3_free(pReader->aNode); - } - sqlite3_blob_close(pReader->pBlob); - } - sqlite3_free(pReader); -} - -/* -** Allocate a new SegReader object. -*/ -int sqlite3Fts3SegReaderNew( - int iAge, /* Segment "age". */ - int bLookup, /* True for a lookup only */ - sqlite3_int64 iStartLeaf, /* First leaf to traverse */ - sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ - sqlite3_int64 iEndBlock, /* Final block of segment */ - const char *zRoot, /* Buffer containing root node */ - int nRoot, /* Size of buffer containing root node */ - Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ -){ - Fts3SegReader *pReader; /* Newly allocated SegReader object */ - int nExtra = 0; /* Bytes to allocate segment root node */ - - assert( zRoot!=0 || nRoot==0 ); -#ifdef CORRUPT_DB - assert( zRoot!=0 || CORRUPT_DB ); -#endif - - if( iStartLeaf==0 ){ - if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB; - nExtra = nRoot + FTS3_NODE_PADDING; - } - - pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra); - if( !pReader ){ - return SQLITE_NOMEM; - } - memset(pReader, 0, sizeof(Fts3SegReader)); - pReader->iIdx = iAge; - pReader->bLookup = bLookup!=0; - pReader->iStartBlock = iStartLeaf; - pReader->iLeafEndBlock = iEndLeaf; - pReader->iEndBlock = iEndBlock; - - if( nExtra ){ - /* The entire segment is stored in the root node. */ - pReader->aNode = (char *)&pReader[1]; - pReader->rootOnly = 1; - pReader->nNode = nRoot; - if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot); - memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING); - }else{ - pReader->iCurrentBlock = iStartLeaf-1; - } - *ppReader = pReader; - return SQLITE_OK; -} - -/* -** This is a comparison function used as a qsort() callback when sorting -** an array of pending terms by term. This occurs as part of flushing -** the contents of the pending-terms hash table to the database. -*/ -static int SQLITE_CDECL fts3CompareElemByTerm( - const void *lhs, - const void *rhs -){ - char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); - char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); - int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); - int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs); - - int n = (n1aIndex */ - const char *zTerm, /* Term to search for */ - int nTerm, /* Size of buffer zTerm */ - int bPrefix, /* True for a prefix iterator */ - Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */ -){ - Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */ - Fts3HashElem *pE; /* Iterator variable */ - Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */ - int nElem = 0; /* Size of array at aElem */ - int rc = SQLITE_OK; /* Return Code */ - Fts3Hash *pHash; - - pHash = &p->aIndex[iIndex].hPending; - if( bPrefix ){ - int nAlloc = 0; /* Size of allocated array at aElem */ - - for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){ - char *zKey = (char *)fts3HashKey(pE); - int nKey = fts3HashKeysize(pE); - if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){ - if( nElem==nAlloc ){ - Fts3HashElem **aElem2; - nAlloc += 16; - aElem2 = (Fts3HashElem **)sqlite3_realloc( - aElem, nAlloc*sizeof(Fts3HashElem *) - ); - if( !aElem2 ){ - rc = SQLITE_NOMEM; - nElem = 0; - break; - } - aElem = aElem2; - } - - aElem[nElem++] = pE; - } - } - - /* If more than one term matches the prefix, sort the Fts3HashElem - ** objects in term order using qsort(). This uses the same comparison - ** callback as is used when flushing terms to disk. - */ - if( nElem>1 ){ - qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm); - } - - }else{ - /* The query is a simple term lookup that matches at most one term in - ** the index. All that is required is a straight hash-lookup. - ** - ** Because the stack address of pE may be accessed via the aElem pointer - ** below, the "Fts3HashElem *pE" must be declared so that it is valid - ** within this entire function, not just this "else{...}" block. - */ - pE = fts3HashFindElem(pHash, zTerm, nTerm); - if( pE ){ - aElem = &pE; - nElem = 1; - } - } - - if( nElem>0 ){ - int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); - pReader = (Fts3SegReader *)sqlite3_malloc(nByte); - if( !pReader ){ - rc = SQLITE_NOMEM; - }else{ - memset(pReader, 0, nByte); - pReader->iIdx = 0x7FFFFFFF; - pReader->ppNextElem = (Fts3HashElem **)&pReader[1]; - memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *)); - } - } - - if( bPrefix ){ - sqlite3_free(aElem); - } - *ppReader = pReader; - return rc; -} - -/* -** Compare the entries pointed to by two Fts3SegReader structures. -** Comparison is as follows: -** -** 1) EOF is greater than not EOF. -** -** 2) The current terms (if any) are compared using memcmp(). If one -** term is a prefix of another, the longer term is considered the -** larger. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc; - if( pLhs->aNode && pRhs->aNode ){ - int rc2 = pLhs->nTerm - pRhs->nTerm; - if( rc2<0 ){ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm); - }else{ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm); - } - if( rc==0 ){ - rc = rc2; - } - }else{ - rc = (pLhs->aNode==0) - (pRhs->aNode==0); - } - if( rc==0 ){ - rc = pRhs->iIdx - pLhs->iIdx; - } - assert( rc!=0 ); - return rc; -} - -/* -** A different comparison function for SegReader structures. In this -** version, it is assumed that each SegReader points to an entry in -** a doclist for identical terms. Comparison is made as follows: -** -** 1) EOF (end of doclist in this case) is greater than not EOF. -** -** 2) By current docid. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} -static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} - -/* -** Compare the term that the Fts3SegReader object passed as the first argument -** points to with the term specified by arguments zTerm and nTerm. -** -** If the pSeg iterator is already at EOF, return 0. Otherwise, return -** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are -** equal, or +ve if the pSeg term is greater than zTerm/nTerm. -*/ -static int fts3SegReaderTermCmp( - Fts3SegReader *pSeg, /* Segment reader object */ - const char *zTerm, /* Term to compare to */ - int nTerm /* Size of term zTerm in bytes */ -){ - int res = 0; - if( pSeg->aNode ){ - if( pSeg->nTerm>nTerm ){ - res = memcmp(pSeg->zTerm, zTerm, nTerm); - }else{ - res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm); - } - if( res==0 ){ - res = pSeg->nTerm-nTerm; - } - } - return res; -} - -/* -** Argument apSegment is an array of nSegment elements. It is known that -** the final (nSegment-nSuspect) members are already in sorted order -** (according to the comparison function provided). This function shuffles -** the array around until all entries are in sorted order. -*/ -static void fts3SegReaderSort( - Fts3SegReader **apSegment, /* Array to sort entries of */ - int nSegment, /* Size of apSegment array */ - int nSuspect, /* Unsorted entry count */ - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */ -){ - int i; /* Iterator variable */ - - assert( nSuspect<=nSegment ); - - if( nSuspect==nSegment ) nSuspect--; - for(i=nSuspect-1; i>=0; i--){ - int j; - for(j=i; j<(nSegment-1); j++){ - Fts3SegReader *pTmp; - if( xCmp(apSegment[j], apSegment[j+1])<0 ) break; - pTmp = apSegment[j+1]; - apSegment[j+1] = apSegment[j]; - apSegment[j] = pTmp; - } - } - -#ifndef NDEBUG - /* Check that the list really is sorted now. */ - for(i=0; i<(nSuspect-1); i++){ - assert( xCmp(apSegment[i], apSegment[i+1])<0 ); - } -#endif -} - -/* -** Insert a record into the %_segments table. -*/ -static int fts3WriteSegment( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iBlock, /* Block id for new block */ - char *z, /* Pointer to buffer containing block data */ - int n /* Size of buffer z in bytes */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iBlock); - sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); - } - return rc; -} - -/* -** Find the largest relative level number in the table. If successful, set -** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs, -** set *pnMax to zero and return an SQLite error code. -*/ -int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){ - int rc; - int mxLevel = 0; - sqlite3_stmt *pStmt = 0; - - rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - mxLevel = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - *pnMax = mxLevel; - return rc; -} - -/* -** Insert a record into the %_segdir table. -*/ -static int fts3WriteSegdir( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ - int iIdx, /* Value for "idx" field */ - sqlite3_int64 iStartBlock, /* Value for "start_block" field */ - sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ - sqlite3_int64 iEndBlock, /* Value for "end_block" field */ - sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */ - char *zRoot, /* Blob value for "root" field */ - int nRoot /* Number of bytes in buffer zRoot */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iLevel); - sqlite3_bind_int(pStmt, 2, iIdx); - sqlite3_bind_int64(pStmt, 3, iStartBlock); - sqlite3_bind_int64(pStmt, 4, iLeafEndBlock); - if( nLeafData==0 ){ - sqlite3_bind_int64(pStmt, 5, iEndBlock); - }else{ - char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData); - if( !zEnd ) return SQLITE_NOMEM; - sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free); - } - sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 6); - } - return rc; -} - -/* -** Return the size of the common prefix (if any) shared by zPrev and -** zNext, in bytes. For example, -** -** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3 -** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2 -** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0 -*/ -static int fts3PrefixCompress( - const char *zPrev, /* Buffer containing previous term */ - int nPrev, /* Size of buffer zPrev in bytes */ - const char *zNext, /* Buffer containing next term */ - int nNext /* Size of buffer zNext in bytes */ -){ - int n; - UNUSED_PARAMETER(nNext); - for(n=0; nnData; /* Current size of node in bytes */ - int nReq = nData; /* Required space after adding zTerm */ - int nPrefix; /* Number of bytes of prefix compression */ - int nSuffix; /* Suffix length */ - - nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; - if( nReq<=p->nNodeSize || !pTree->zTerm ){ - - if( nReq>p->nNodeSize ){ - /* An unusual case: this is the first term to be added to the node - ** and the static node buffer (p->nNodeSize bytes) is not large - ** enough. Use a separately malloced buffer instead This wastes - ** p->nNodeSize bytes, but since this scenario only comes about when - ** the database contain two terms that share a prefix of almost 2KB, - ** this is not expected to be a serious problem. - */ - assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)sqlite3_malloc(nReq); - if( !pTree->aData ){ - return SQLITE_NOMEM; - } - } - - if( pTree->zTerm ){ - /* There is no prefix-length field for first term in a node */ - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix); - } - - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix); - memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix); - pTree->nData = nData + nSuffix; - pTree->nEntry++; - - if( isCopyTerm ){ - if( pTree->nMalloczMalloc, nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pTree->nMalloc = nTerm*2; - pTree->zMalloc = zNew; - } - pTree->zTerm = pTree->zMalloc; - memcpy(pTree->zTerm, zTerm, nTerm); - pTree->nTerm = nTerm; - }else{ - pTree->zTerm = (char *)zTerm; - pTree->nTerm = nTerm; - } - return SQLITE_OK; - } - } - - /* If control flows to here, it was not possible to append zTerm to the - ** current node. Create a new node (a right-sibling of the current node). - ** If this is the first node in the tree, the term is added to it. - ** - ** Otherwise, the term is not added to the new node, it is left empty for - ** now. Instead, the term is inserted into the parent of pTree. If pTree - ** has no parent, one is created here. - */ - pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); - if( !pNew ){ - return SQLITE_NOMEM; - } - memset(pNew, 0, sizeof(SegmentNode)); - pNew->nData = 1 + FTS3_VARINT_MAX; - pNew->aData = (char *)&pNew[1]; - - if( pTree ){ - SegmentNode *pParent = pTree->pParent; - rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm); - if( pTree->pParent==0 ){ - pTree->pParent = pParent; - } - pTree->pRight = pNew; - pNew->pLeftmost = pTree->pLeftmost; - pNew->pParent = pParent; - pNew->zMalloc = pTree->zMalloc; - pNew->nMalloc = pTree->nMalloc; - pTree->zMalloc = 0; - }else{ - pNew->pLeftmost = pNew; - rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm); - } - - *ppTree = pNew; - return rc; -} - -/* -** Helper function for fts3NodeWrite(). -*/ -static int fts3TreeFinishNode( - SegmentNode *pTree, - int iHeight, - sqlite3_int64 iLeftChild -){ - int nStart; - assert( iHeight>=1 && iHeight<128 ); - nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); - pTree->aData[nStart] = (char)iHeight; - sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild); - return nStart; -} - -/* -** Write the buffer for the segment node pTree and all of its peers to the -** database. Then call this function recursively to write the parent of -** pTree and its peers to the database. -** -** Except, if pTree is a root node, do not write it to the database. Instead, -** set output variables *paRoot and *pnRoot to contain the root node. -** -** If successful, SQLITE_OK is returned and output variable *piLast is -** set to the largest blockid written to the database (or zero if no -** blocks were written to the db). Otherwise, an SQLite error code is -** returned. -*/ -static int fts3NodeWrite( - Fts3Table *p, /* Virtual table handle */ - SegmentNode *pTree, /* SegmentNode handle */ - int iHeight, /* Height of this node in tree */ - sqlite3_int64 iLeaf, /* Block id of first leaf node */ - sqlite3_int64 iFree, /* Block id of next free slot in %_segments */ - sqlite3_int64 *piLast, /* OUT: Block id of last entry written */ - char **paRoot, /* OUT: Data for root node */ - int *pnRoot /* OUT: Size of root node in bytes */ -){ - int rc = SQLITE_OK; - - if( !pTree->pParent ){ - /* Root node of the tree. */ - int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf); - *piLast = iFree-1; - *pnRoot = pTree->nData - nStart; - *paRoot = &pTree->aData[nStart]; - }else{ - SegmentNode *pIter; - sqlite3_int64 iNextFree = iFree; - sqlite3_int64 iNextLeaf = iLeaf; - for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){ - int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf); - int nWrite = pIter->nData - nStart; - - rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite); - iNextFree++; - iNextLeaf += (pIter->nEntry+1); - } - if( rc==SQLITE_OK ){ - assert( iNextLeaf==iFree ); - rc = fts3NodeWrite( - p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot - ); - } - } - - return rc; -} - -/* -** Free all memory allocations associated with the tree pTree. -*/ -static void fts3NodeFree(SegmentNode *pTree){ - if( pTree ){ - SegmentNode *p = pTree->pLeftmost; - fts3NodeFree(p->pParent); - while( p ){ - SegmentNode *pRight = p->pRight; - if( p->aData!=(char *)&p[1] ){ - sqlite3_free(p->aData); - } - assert( pRight==0 || p->zMalloc==0 ); - sqlite3_free(p->zMalloc); - sqlite3_free(p); - p = pRight; - } - } -} - -/* -** Add a term to the segment being constructed by the SegmentWriter object -** *ppWriter. When adding the first term to a segment, *ppWriter should -** be passed NULL. This function will allocate a new SegmentWriter object -** and return it via the input/output variable *ppWriter in this case. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterAdd( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ - int isCopyTerm, /* True if buffer zTerm must be copied */ - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of term in bytes */ - const char *aDoclist, /* Pointer to buffer containing doclist */ - int nDoclist /* Size of doclist in bytes */ -){ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - int nReq; /* Number of bytes required on leaf page */ - int nData; - SegmentWriter *pWriter = *ppWriter; - - if( !pWriter ){ - int rc; - sqlite3_stmt *pStmt; - - /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter)); - if( !pWriter ) return SQLITE_NOMEM; - memset(pWriter, 0, sizeof(SegmentWriter)); - *ppWriter = pWriter; - - /* Allocate a buffer in which to accumulate data */ - pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); - if( !pWriter->aData ) return SQLITE_NOMEM; - pWriter->nSize = p->nNodeSize; - - /* Find the next free blockid in the %_segments table */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - pWriter->iFree = sqlite3_column_int64(pStmt, 0); - pWriter->iFirst = pWriter->iFree; - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ) return rc; - } - nData = pWriter->nData; - - nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of - ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when - ** compared with BINARY collation. This indicates corruption. */ - if( nSuffix<=0 ) return FTS_CORRUPT_VTAB; - - /* Figure out how many bytes are required by this new entry */ - nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ - nSuffix + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - - if( nData>0 && nData+nReq>p->nNodeSize ){ - int rc; - - /* The current leaf node is full. Write it out to the database. */ - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); - if( rc!=SQLITE_OK ) return rc; - p->nLeafAdd++; - - /* Add the current term to the interior node tree. The term added to - ** the interior tree must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pWriter->zTerm), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - assert( nPrefixpTree, isCopyTerm, zTerm, nPrefix+1); - if( rc!=SQLITE_OK ) return rc; - - nData = 0; - pWriter->nTerm = 0; - - nPrefix = 0; - nSuffix = nTerm; - nReq = 1 + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */ - nTerm + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - } - - /* Increase the total number of bytes written to account for the new entry. */ - pWriter->nLeafData += nReq; - - /* If the buffer currently allocated is too small for this entry, realloc - ** the buffer to make it large enough. - */ - if( nReq>pWriter->nSize ){ - char *aNew = sqlite3_realloc(pWriter->aData, nReq); - if( !aNew ) return SQLITE_NOMEM; - pWriter->aData = aNew; - pWriter->nSize = nReq; - } - assert( nData+nReq<=pWriter->nSize ); - - /* Append the prefix-compressed term and doclist to the buffer. */ - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix); - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix); - memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix); - nData += nSuffix; - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist); - memcpy(&pWriter->aData[nData], aDoclist, nDoclist); - pWriter->nData = nData + nDoclist; - - /* Save the current term so that it can be used to prefix-compress the next. - ** If the isCopyTerm parameter is true, then the buffer pointed to by - ** zTerm is transient, so take a copy of the term data. Otherwise, just - ** store a copy of the pointer. - */ - if( isCopyTerm ){ - if( nTerm>pWriter->nMalloc ){ - char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pWriter->nMalloc = nTerm*2; - pWriter->zMalloc = zNew; - pWriter->zTerm = zNew; - } - assert( pWriter->zTerm==pWriter->zMalloc ); - memcpy(pWriter->zTerm, zTerm, nTerm); - }else{ - pWriter->zTerm = (char *)zTerm; - } - pWriter->nTerm = nTerm; - - return SQLITE_OK; -} - -/* -** Flush all data associated with the SegmentWriter object pWriter to the -** database. This function must be called after all terms have been added -** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is -** returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterFlush( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter *pWriter, /* SegmentWriter to flush to the db */ - sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */ - int iIdx /* Value for 'idx' column of %_segdir */ -){ - int rc; /* Return code */ - if( pWriter->pTree ){ - sqlite3_int64 iLast = 0; /* Largest block id written to database */ - sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ - char *zRoot = NULL; /* Pointer to buffer containing root node */ - int nRoot = 0; /* Size of buffer zRoot */ - - iLastLeaf = pWriter->iFree; - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); - if( rc==SQLITE_OK ){ - rc = fts3NodeWrite(p, pWriter->pTree, 1, - pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, iLevel, iIdx, - pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot); - } - }else{ - /* The entire tree fits on the root node. Write it to the segdir table. */ - rc = fts3WriteSegdir(p, iLevel, iIdx, - 0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData); - } - p->nLeafAdd++; - return rc; -} - -/* -** Release all memory held by the SegmentWriter object passed as the -** first argument. -*/ -static void fts3SegWriterFree(SegmentWriter *pWriter){ - if( pWriter ){ - sqlite3_free(pWriter->aData); - sqlite3_free(pWriter->zMalloc); - fts3NodeFree(pWriter->pTree); - sqlite3_free(pWriter); - } -} - -/* -** The first value in the apVal[] array is assumed to contain an integer. -** This function tests if there exist any documents with docid values that -** are different from that integer. i.e. if deleting the document with docid -** pRowid would mean the FTS3 table were empty. -** -** If successful, *pisEmpty is set to true if the table is empty except for -** document pRowid, or false otherwise, and SQLITE_OK is returned. If an -** error occurs, an SQLite error code is returned. -*/ -static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){ - sqlite3_stmt *pStmt; - int rc; - if( p->zContentTbl ){ - /* If using the content=xxx option, assume the table is never empty */ - *pisEmpty = 0; - rc = SQLITE_OK; - }else{ - rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pisEmpty = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - } - return rc; -} - -/* -** Set *pnMax to the largest segment level in the database for the index -** iIndex. -** -** Segment levels are stored in the 'level' column of the %_segdir table. -** -** Return SQLITE_OK if successful, or an SQLite error code if not. -*/ -static int fts3SegmentMaxLevel( - Fts3Table *p, - int iLangid, - int iIndex, - sqlite3_int64 *pnMax -){ - sqlite3_stmt *pStmt; - int rc; - assert( iIndex>=0 && iIndexnIndex ); - - /* Set pStmt to the compiled version of: - ** - ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? - ** - ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). - */ - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pnMax = sqlite3_column_int64(pStmt, 0); - } - return sqlite3_reset(pStmt); -} - -/* -** iAbsLevel is an absolute level that may be assumed to exist within -** the database. This function checks if it is the largest level number -** within its index. Assuming no error occurs, *pbMax is set to 1 if -** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK -** is returned. If an error occurs, an error code is returned and the -** final value of *pbMax is undefined. -*/ -static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){ - - /* Set pStmt to the compiled version of: - ** - ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? - ** - ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). - */ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pStmt, 1, iAbsLevel+1); - sqlite3_bind_int64(pStmt, 2, - ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL - ); - - *pbMax = 0; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL; - } - return sqlite3_reset(pStmt); -} - -/* -** Delete all entries in the %_segments table associated with the segment -** opened with seg-reader pSeg. This function does not affect the contents -** of the %_segdir table. -*/ -static int fts3DeleteSegment( - Fts3Table *p, /* FTS table handle */ - Fts3SegReader *pSeg /* Segment to delete */ -){ - int rc = SQLITE_OK; /* Return code */ - if( pSeg->iStartBlock ){ - sqlite3_stmt *pDelete; /* SQL statement to delete rows */ - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock); - sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - } - return rc; -} - -/* -** This function is used after merging multiple segments into a single large -** segment to delete the old, now redundant, segment b-trees. Specifically, -** it: -** -** 1) Deletes all %_segments entries for the segments associated with -** each of the SegReader objects in the array passed as the third -** argument, and -** -** 2) deletes all %_segdir entries with level iLevel, or all %_segdir -** entries regardless of level if (iLevel<0). -** -** SQLITE_OK is returned if successful, otherwise an SQLite error code. -*/ -static int fts3DeleteSegdir( - Fts3Table *p, /* Virtual table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, /* Level of %_segdir entries to delete */ - Fts3SegReader **apSegment, /* Array of SegReader objects */ - int nReader /* Size of array apSegment */ -){ - int rc = SQLITE_OK; /* Return Code */ - int i; /* Iterator variable */ - sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */ - - for(i=0; rc==SQLITE_OK && i=0 || iLevel==FTS3_SEGCURSOR_ALL ); - if( iLevel==FTS3_SEGCURSOR_ALL ){ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pDelete, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** When this function is called, buffer *ppList (size *pnList bytes) contains -** a position list that may (or may not) feature multiple columns. This -** function adjusts the pointer *ppList and the length *pnList so that they -** identify the subset of the position list that corresponds to column iCol. -** -** If there are no entries in the input position list for column iCol, then -** *pnList is set to zero before returning. -** -** If parameter bZero is non-zero, then any part of the input list following -** the end of the output list is zeroed before returning. -*/ -static void fts3ColumnFilter( - int iCol, /* Column to filter on */ - int bZero, /* Zero out anything following *ppList */ - char **ppList, /* IN/OUT: Pointer to position list */ - int *pnList /* IN/OUT: Size of buffer *ppList in bytes */ -){ - char *pList = *ppList; - int nList = *pnList; - char *pEnd = &pList[nList]; - int iCurrent = 0; - char *p = pList; - - assert( iCol>=0 ); - while( 1 ){ - char c = 0; - while( ppMsr->nBuffer ){ - char *pNew; - pMsr->nBuffer = nList*2; - pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer); - if( !pNew ) return SQLITE_NOMEM; - pMsr->aBuffer = pNew; - } - - memcpy(pMsr->aBuffer, pList, nList); - return SQLITE_OK; -} - -int sqlite3Fts3MsrIncrNext( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ - sqlite3_int64 *piDocid, /* OUT: Docid value */ - char **paPoslist, /* OUT: Pointer to position list */ - int *pnPoslist /* OUT: Size of position list in bytes */ -){ - int nMerge = pMsr->nAdvance; - Fts3SegReader **apSegment = pMsr->apSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( nMerge==0 ){ - *paPoslist = 0; - return SQLITE_OK; - } - - while( 1 ){ - Fts3SegReader *pSeg; - pSeg = pMsr->apSegment[0]; - - if( pSeg->pOffsetList==0 ){ - *paPoslist = 0; - break; - }else{ - int rc; - char *pList; - int nList; - int j; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - - rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( rc==SQLITE_OK - && jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - if( rc!=SQLITE_OK ) return rc; - fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); - - if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, nList+1); - if( rc!=SQLITE_OK ) return rc; - assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); - pList = pMsr->aBuffer; - } - - if( pMsr->iColFilter>=0 ){ - fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList); - } - - if( nList>0 ){ - *paPoslist = pList; - *piDocid = iDocid; - *pnPoslist = nList; - break; - } - } - } - - return SQLITE_OK; -} - -static int fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - const char *zTerm, /* Term searched for (or NULL) */ - int nTerm /* Length of zTerm in bytes */ -){ - int i; - int nSeg = pCsr->nSegment; - - /* If the Fts3SegFilter defines a specific term (or term prefix) to search - ** for, then advance each segment iterator until it points to a term of - ** equal or greater value than the specified term. This prevents many - ** unnecessary merge/sort operations for the case where single segment - ** b-tree leaf nodes contain more than one term. - */ - for(i=0; pCsr->bRestart==0 && inSegment; i++){ - int res = 0; - Fts3SegReader *pSeg = pCsr->apSegment[i]; - do { - int rc = fts3SegReaderNext(p, pSeg, 0); - if( rc!=SQLITE_OK ) return rc; - }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 ); - - if( pSeg->bLookup && res!=0 ){ - fts3SegReaderSetEof(pSeg); - } - } - fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp); - - return SQLITE_OK; -} - -int sqlite3Fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - Fts3SegFilter *pFilter /* Restrictions on range of iteration */ -){ - pCsr->pFilter = pFilter; - return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm); -} - -int sqlite3Fts3MsrIncrStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - int iCol, /* Column to match on. */ - const char *zTerm, /* Term to iterate through a doclist for */ - int nTerm /* Number of bytes in zTerm */ -){ - int i; - int rc; - int nSegment = pCsr->nSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - assert( pCsr->pFilter==0 ); - assert( zTerm && nTerm>0 ); - - /* Advance each segment iterator until it points to the term zTerm/nTerm. */ - rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm); - if( rc!=SQLITE_OK ) return rc; - - /* Determine how many of the segments actually point to zTerm/nTerm. */ - for(i=0; iapSegment[i]; - if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){ - break; - } - } - pCsr->nAdvance = i; - - /* Advance each of the segments to point to the first docid. */ - for(i=0; inAdvance; i++){ - rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]); - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(pCsr->apSegment, i, i, xCmp); - - assert( iCol<0 || iColnColumn ); - pCsr->iColFilter = iCol; - - return SQLITE_OK; -} - -/* -** This function is called on a MultiSegReader that has been started using -** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also -** have been made. Calling this function puts the MultiSegReader in such -** a state that if the next two calls are: -** -** sqlite3Fts3SegReaderStart() -** sqlite3Fts3SegReaderStep() -** -** then the entire doclist for the term is available in -** MultiSegReader.aDoclist/nDoclist. -*/ -int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ - int i; /* Used to iterate through segment-readers */ - - assert( pCsr->zTerm==0 ); - assert( pCsr->nTerm==0 ); - assert( pCsr->aDoclist==0 ); - assert( pCsr->nDoclist==0 ); - - pCsr->nAdvance = 0; - pCsr->bRestart = 1; - for(i=0; inSegment; i++){ - pCsr->apSegment[i]->pOffsetList = 0; - pCsr->apSegment[i]->nOffsetList = 0; - pCsr->apSegment[i]->iDocid = 0; - } - - return SQLITE_OK; -} - - -int sqlite3Fts3SegReaderStep( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - int rc = SQLITE_OK; - - int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); - int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); - int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); - int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX); - int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN); - int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST); - - Fts3SegReader **apSegment = pCsr->apSegment; - int nSegment = pCsr->nSegment; - Fts3SegFilter *pFilter = pCsr->pFilter; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( pCsr->nSegment==0 ) return SQLITE_OK; - - do { - int nMerge; - int i; - - /* Advance the first pCsr->nAdvance entries in the apSegment[] array - ** forward. Then sort the list in order of current term again. - */ - for(i=0; inAdvance; i++){ - Fts3SegReader *pSeg = apSegment[i]; - if( pSeg->bLookup ){ - fts3SegReaderSetEof(pSeg); - }else{ - rc = fts3SegReaderNext(p, pSeg, 0); - } - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp); - pCsr->nAdvance = 0; - - /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */ - assert( rc==SQLITE_OK ); - if( apSegment[0]->aNode==0 ) break; - - pCsr->nTerm = apSegment[0]->nTerm; - pCsr->zTerm = apSegment[0]->zTerm; - - /* If this is a prefix-search, and if the term that apSegment[0] points - ** to does not share a suffix with pFilter->zTerm/nTerm, then all - ** required callbacks have been made. In this case exit early. - ** - ** Similarly, if this is a search for an exact match, and the first term - ** of segment apSegment[0] is not a match, exit early. - */ - if( pFilter->zTerm && !isScan ){ - if( pCsr->nTermnTerm - || (!isPrefix && pCsr->nTerm>pFilter->nTerm) - || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) - ){ - break; - } - } - - nMerge = 1; - while( nMergeaNode - && apSegment[nMerge]->nTerm==pCsr->nTerm - && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm) - ){ - nMerge++; - } - - assert( isIgnoreEmpty || (isRequirePos && !isColFilter) ); - if( nMerge==1 - && !isIgnoreEmpty - && !isFirst - && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0) - ){ - pCsr->nDoclist = apSegment[0]->nDoclist; - if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist); - pCsr->aDoclist = pCsr->aBuffer; - }else{ - pCsr->aDoclist = apSegment[0]->aDoclist; - } - if( rc==SQLITE_OK ) rc = SQLITE_ROW; - }else{ - int nDoclist = 0; /* Size of doclist */ - sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */ - - /* The current term of the first nMerge entries in the array - ** of Fts3SegReader objects is the same. The doclists must be merged - ** and a single term returned with the merged doclist. - */ - for(i=0; ipOffsetList ){ - int j; /* Number of segments that share a docid */ - char *pList = 0; - int nList = 0; - int nByte; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - - if( isColFilter ){ - fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList); - } - - if( !isIgnoreEmpty || nList>0 ){ - - /* Calculate the 'docid' delta value to write into the merged - ** doclist. */ - sqlite3_int64 iDelta; - if( p->bDescIdx && nDoclist>0 ){ - iDelta = iPrev - iDocid; - }else{ - iDelta = iDocid - iPrev; - } - if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){ - return FTS_CORRUPT_VTAB; - } - assert( nDoclist>0 || iDelta==iDocid ); - - nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - if( nDoclist+nByte>pCsr->nBuffer ){ - char *aNew; - pCsr->nBuffer = (nDoclist+nByte)*2; - aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); - if( !aNew ){ - return SQLITE_NOMEM; - } - pCsr->aBuffer = aNew; - } - - if( isFirst ){ - char *a = &pCsr->aBuffer[nDoclist]; - int nWrite; - - nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a); - if( nWrite ){ - iPrev = iDocid; - nDoclist += nWrite; - } - }else{ - nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta); - iPrev = iDocid; - if( isRequirePos ){ - memcpy(&pCsr->aBuffer[nDoclist], pList, nList); - nDoclist += nList; - pCsr->aBuffer[nDoclist++] = '\0'; - } - } - } - - fts3SegReaderSort(apSegment, nMerge, j, xCmp); - } - if( nDoclist>0 ){ - pCsr->aDoclist = pCsr->aBuffer; - pCsr->nDoclist = nDoclist; - rc = SQLITE_ROW; - } - } - pCsr->nAdvance = nMerge; - }while( rc==SQLITE_OK ); - - return rc; -} - - -void sqlite3Fts3SegReaderFinish( - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - if( pCsr ){ - int i; - for(i=0; inSegment; i++){ - sqlite3Fts3SegReaderFree(pCsr->apSegment[i]); - } - sqlite3_free(pCsr->apSegment); - sqlite3_free(pCsr->aBuffer); - - pCsr->nSegment = 0; - pCsr->apSegment = 0; - pCsr->aBuffer = 0; - } -} - -/* -** Decode the "end_block" field, selected by column iCol of the SELECT -** statement passed as the first argument. -** -** The "end_block" field may contain either an integer, or a text field -** containing the text representation of two non-negative integers separated -** by one or more space (0x20) characters. In the first case, set *piEndBlock -** to the integer value and *pnByte to zero before returning. In the second, -** set *piEndBlock to the first value and *pnByte to the second. -*/ -static void fts3ReadEndBlockField( - sqlite3_stmt *pStmt, - int iCol, - i64 *piEndBlock, - i64 *pnByte -){ - const unsigned char *zText = sqlite3_column_text(pStmt, iCol); - if( zText ){ - int i; - int iMul = 1; - i64 iVal = 0; - for(i=0; zText[i]>='0' && zText[i]<='9'; i++){ - iVal = iVal*10 + (zText[i] - '0'); - } - *piEndBlock = iVal; - while( zText[i]==' ' ) i++; - iVal = 0; - if( zText[i]=='-' ){ - i++; - iMul = -1; - } - for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){ - iVal = iVal*10 + (zText[i] - '0'); - } - *pnByte = (iVal * (i64)iMul); - } -} - - -/* -** A segment of size nByte bytes has just been written to absolute level -** iAbsLevel. Promote any segments that should be promoted as a result. -*/ -static int fts3PromoteSegments( - Fts3Table *p, /* FTS table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level just updated */ - sqlite3_int64 nByte /* Size of new segment at iAbsLevel */ -){ - int rc = SQLITE_OK; - sqlite3_stmt *pRange; - - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0); - - if( rc==SQLITE_OK ){ - int bOk = 0; - i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1; - i64 nLimit = (nByte*3)/2; - - /* Loop through all entries in the %_segdir table corresponding to - ** segments in this index on levels greater than iAbsLevel. If there is - ** at least one such segment, and it is possible to determine that all - ** such segments are smaller than nLimit bytes in size, they will be - ** promoted to level iAbsLevel. */ - sqlite3_bind_int64(pRange, 1, iAbsLevel+1); - sqlite3_bind_int64(pRange, 2, iLast); - while( SQLITE_ROW==sqlite3_step(pRange) ){ - i64 nSize = 0, dummy; - fts3ReadEndBlockField(pRange, 2, &dummy, &nSize); - if( nSize<=0 || nSize>nLimit ){ - /* If nSize==0, then the %_segdir.end_block field does not not - ** contain a size value. This happens if it was written by an - ** old version of FTS. In this case it is not possible to determine - ** the size of the segment, and so segment promotion does not - ** take place. */ - bOk = 0; - break; - } - bOk = 1; - } - rc = sqlite3_reset(pRange); - - if( bOk ){ - int iIdx = 0; - sqlite3_stmt *pUpdate1 = 0; - sqlite3_stmt *pUpdate2 = 0; - - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); - } - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0); - } - - if( rc==SQLITE_OK ){ - - /* Loop through all %_segdir entries for segments in this index with - ** levels equal to or greater than iAbsLevel. As each entry is visited, - ** updated it to set (level = -1) and (idx = N), where N is 0 for the - ** oldest segment in the range, 1 for the next oldest, and so on. - ** - ** In other words, move all segments being promoted to level -1, - ** setting the "idx" fields as appropriate to keep them in the same - ** order. The contents of level -1 (which is never used, except - ** transiently here), will be moved back to level iAbsLevel below. */ - sqlite3_bind_int64(pRange, 1, iAbsLevel); - while( SQLITE_ROW==sqlite3_step(pRange) ){ - sqlite3_bind_int(pUpdate1, 1, iIdx++); - sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0)); - sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1)); - sqlite3_step(pUpdate1); - rc = sqlite3_reset(pUpdate1); - if( rc!=SQLITE_OK ){ - sqlite3_reset(pRange); - break; - } - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3_reset(pRange); - } - - /* Move level -1 to level iAbsLevel */ - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate2, 1, iAbsLevel); - sqlite3_step(pUpdate2); - rc = sqlite3_reset(pUpdate2); - } - } - } - - - return rc; -} - -/* -** Merge all level iLevel segments in the database into a single -** iLevel+1 segment. Or, if iLevel<0, merge all segments into a -** single segment with a level equal to the numerically largest level -** currently present in the database. -** -** If this function is called with iLevel<0, but there is only one -** segment in the database, SQLITE_DONE is returned immediately. -** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, -** an SQLite error code is returned. -*/ -static int fts3SegmentMerge( - Fts3Table *p, - int iLangid, /* Language id to merge */ - int iIndex, /* Index in p->aIndex[] to merge */ - int iLevel /* Level to merge */ -){ - int rc; /* Return code */ - int iIdx = 0; /* Index of new segment */ - sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */ - SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ - Fts3SegFilter filter; /* Segment term filter condition */ - Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ - int bIgnoreEmpty = 0; /* True to ignore empty segments */ - i64 iMaxLevel = 0; /* Max level number for this index/langid */ - - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevel=0 && iIndexnIndex ); - - rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); - if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; - - if( iLevel!=FTS3_SEGCURSOR_PENDING ){ - rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel); - if( rc!=SQLITE_OK ) goto finished; - } - - if( iLevel==FTS3_SEGCURSOR_ALL ){ - /* This call is to merge all segments in the database to a single - ** segment. The level of the new segment is equal to the numerically - ** greatest segment level currently present in the database for this - ** index. The idx of the new segment is always 0. */ - if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){ - rc = SQLITE_DONE; - goto finished; - } - iNewLevel = iMaxLevel; - bIgnoreEmpty = 1; - - }else{ - /* This call is to merge all segments at level iLevel. find the next - ** available segment index at level iLevel+1. The call to - ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to - ** a single iLevel+2 segment if necessary. */ - assert( FTS3_SEGCURSOR_PENDING==-1 ); - iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); - bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel); - } - if( rc!=SQLITE_OK ) goto finished; - - assert( csr.nSegment>0 ); - assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); - assert( iNewLevelnLeafData); - } - } - } - - finished: - fts3SegWriterFree(pWriter); - sqlite3Fts3SegReaderFinish(&csr); - return rc; -} - - -/* -** Flush the contents of pendingTerms to level 0 segments. -*/ -int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ - int rc = SQLITE_OK; - int i; - - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - sqlite3Fts3PendingTermsClear(p); - - /* Determine the auto-incr-merge setting if unknown. If enabled, - ** estimate the number of leaf blocks of content to be written - */ - if( rc==SQLITE_OK && p->bHasStat - && p->nAutoincrmerge==0xff && p->nLeafAdd>0 - ){ - sqlite3_stmt *pStmt = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - rc = sqlite3_step(pStmt); - if( rc==SQLITE_ROW ){ - p->nAutoincrmerge = sqlite3_column_int(pStmt, 0); - if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8; - }else if( rc==SQLITE_DONE ){ - p->nAutoincrmerge = 0; - } - rc = sqlite3_reset(pStmt); - } - } - return rc; -} - -/* -** Encode N integers as varints into a blob. -*/ -static void fts3EncodeIntArray( - int N, /* The number of integers to encode */ - u32 *a, /* The integer values */ - char *zBuf, /* Write the BLOB here */ - int *pNBuf /* Write number of bytes if zBuf[] used here */ -){ - int i, j; - for(i=j=0; iiPrevDocid. The sizes are encoded as -** a blob of varints. -*/ -static void fts3InsertDocsize( - int *pRC, /* Result code */ - Fts3Table *p, /* Table into which to insert */ - u32 *aSz /* Sizes of each column, in tokens */ -){ - char *pBlob; /* The BLOB encoding of the document size */ - int nBlob; /* Number of bytes in the BLOB */ - sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ - int rc; /* Result code from subfunctions */ - - if( *pRC ) return; - pBlob = sqlite3_malloc( 10*p->nColumn ); - if( pBlob==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); - if( rc ){ - sqlite3_free(pBlob); - *pRC = rc; - return; - } - sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); -} - -/* -** Record 0 of the %_stat table contains a blob consisting of N varints, -** where N is the number of user defined columns in the fts3 table plus -** two. If nCol is the number of user defined columns, then values of the -** varints are set as follows: -** -** Varint 0: Total number of rows in the table. -** -** Varint 1..nCol: For each column, the total number of tokens stored in -** the column for all rows of the table. -** -** Varint 1+nCol: The total size, in bytes, of all text values in all -** columns of all rows of the table. -** -*/ -static void fts3UpdateDocTotals( - int *pRC, /* The result code */ - Fts3Table *p, /* Table being updated */ - u32 *aSzIns, /* Size increases */ - u32 *aSzDel, /* Size decreases */ - int nChng /* Change in the number of documents */ -){ - char *pBlob; /* Storage for BLOB written into %_stat */ - int nBlob; /* Size of BLOB written into %_stat */ - u32 *a; /* Array of integers that becomes the BLOB */ - sqlite3_stmt *pStmt; /* Statement for reading and writing */ - int i; /* Loop counter */ - int rc; /* Result code from subfunctions */ - - const int nStat = p->nColumn+2; - - if( *pRC ) return; - a = sqlite3_malloc( (sizeof(u32)+10)*nStat ); - if( a==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - pBlob = (char*)&a[nStat]; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - fts3DecodeIntArray(nStat, a, - sqlite3_column_blob(pStmt, 0), - sqlite3_column_bytes(pStmt, 0)); - }else{ - memset(a, 0, sizeof(u32)*(nStat) ); - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - sqlite3_free(a); - *pRC = rc; - return; - } - if( nChng<0 && a[0]<(u32)(-nChng) ){ - a[0] = 0; - }else{ - a[0] += nChng; - } - for(i=0; inColumn+1; i++){ - u32 x = a[i+1]; - if( x+aSzIns[i] < aSzDel[i] ){ - x = 0; - }else{ - x = x + aSzIns[i] - aSzDel[i]; - } - a[i+1] = x; - } - fts3EncodeIntArray(nStat, a, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); - sqlite3_bind_null(pStmt, 2); - sqlite3_free(a); -} - -/* -** Merge the entire database so that there is one segment for each -** iIndex/iLangid combination. -*/ -static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ - int bSeenDone = 0; - int rc; - sqlite3_stmt *pAllLangid = 0; - - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); - while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int i; - int iLangid = sqlite3_column_int(pAllLangid, 0); - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); - if( rc==SQLITE_DONE ){ - bSeenDone = 1; - rc = SQLITE_OK; - } - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - sqlite3Fts3SegmentsClose(p); - sqlite3Fts3PendingTermsClear(p); - - return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; -} - -/* -** This function is called when the user executes the following statement: -** -** INSERT INTO () VALUES('rebuild'); -** -** The entire FTS index is discarded and rebuilt. If the table is one -** created using the content=xxx option, then the new index is based on -** the current contents of the xxx table. Otherwise, it is rebuilt based -** on the contents of the %_content table. -*/ -static int fts3DoRebuild(Fts3Table *p){ - int rc; /* Return Code */ - - rc = fts3DeleteAll(p, 0); - if( rc==SQLITE_OK ){ - u32 *aSz = 0; - u32 *aSzIns = 0; - u32 *aSzDel = 0; - sqlite3_stmt *pStmt = 0; - int nEntry = 0; - - /* Compose and prepare an SQL statement to loop through the content table */ - char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - if( rc==SQLITE_OK ){ - int nByte = sizeof(u32) * (p->nColumn+1)*3; - aSz = (u32 *)sqlite3_malloc(nByte); - if( aSz==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(aSz, 0, nByte); - aSzIns = &aSz[p->nColumn+1]; - aSzDel = &aSzIns[p->nColumn+1]; - } - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - int iCol; - int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); - memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - if( p->abNotindexed[iCol]==0 ){ - const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); - rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); - aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); - } - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSz); - } - if( rc!=SQLITE_OK ){ - sqlite3_finalize(pStmt); - pStmt = 0; - }else{ - nEntry++; - for(iCol=0; iCol<=p->nColumn; iCol++){ - aSzIns[iCol] += aSz[iCol]; - } - } - } - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry); - } - sqlite3_free(aSz); - - if( pStmt ){ - int rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - return rc; -} - - -/* -** This function opens a cursor used to read the input data for an -** incremental merge operation. Specifically, it opens a cursor to scan -** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute -** level iAbsLevel. -*/ -static int fts3IncrmergeCsr( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to open */ - int nSeg, /* Number of segments to merge */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc; /* Return Code */ - sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ - int nByte; /* Bytes allocated at pCsr->apSegment[] */ - - /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ - memset(pCsr, 0, sizeof(*pCsr)); - nByte = sizeof(Fts3SegReader *) * nSeg; - pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); - - if( pCsr->apSegment==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->apSegment, 0, nByte); - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - } - if( rc==SQLITE_OK ){ - int i; - int rc2; - sqlite3_bind_int64(pStmt, 1, iAbsLevel); - assert( pCsr->nSegment==0 ); - for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && iapSegment[i] - ); - pCsr->nSegment++; - } - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -typedef struct IncrmergeWriter IncrmergeWriter; -typedef struct NodeWriter NodeWriter; -typedef struct Blob Blob; -typedef struct NodeReader NodeReader; - -/* -** An instance of the following structure is used as a dynamic buffer -** to build up nodes or other blobs of data in. -** -** The function blobGrowBuffer() is used to extend the allocation. -*/ -struct Blob { - char *a; /* Pointer to allocation */ - int n; /* Number of valid bytes of data in a[] */ - int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ -}; - -/* -** This structure is used to build up buffers containing segment b-tree -** nodes (blocks). -*/ -struct NodeWriter { - sqlite3_int64 iBlock; /* Current block id */ - Blob key; /* Last key written to the current block */ - Blob block; /* Current block image */ -}; - -/* -** An object of this type contains the state required to create or append -** to an appendable b-tree segment. -*/ -struct IncrmergeWriter { - int nLeafEst; /* Space allocated for leaf blocks */ - int nWork; /* Number of leaf pages flushed */ - sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ - int iIdx; /* Index of *output* segment in iAbsLevel+1 */ - sqlite3_int64 iStart; /* Block number of first allocated block */ - sqlite3_int64 iEnd; /* Block number of last allocated block */ - sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */ - u8 bNoLeafData; /* If true, store 0 for segment size */ - NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT]; -}; - -/* -** An object of the following type is used to read data from a single -** FTS segment node. See the following functions: -** -** nodeReaderInit() -** nodeReaderNext() -** nodeReaderRelease() -*/ -struct NodeReader { - const char *aNode; - int nNode; - int iOff; /* Current offset within aNode[] */ - - /* Output variables. Containing the current node entry. */ - sqlite3_int64 iChild; /* Pointer to child node */ - Blob term; /* Current term */ - const char *aDoclist; /* Pointer to doclist */ - int nDoclist; /* Size of doclist in bytes */ -}; - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if the allocation at pBlob->a is not already at least nMin -** bytes in size, extend (realloc) it to be so. -** -** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a -** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc -** to reflect the new size of the pBlob->a[] buffer. -*/ -static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ - if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ - int nAlloc = nMin; - char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc); - if( a ){ - pBlob->nAlloc = nAlloc; - pBlob->a = a; - }else{ - *pRc = SQLITE_NOMEM; - } - } -} - -/* -** Attempt to advance the node-reader object passed as the first argument to -** the next entry on the node. -** -** Return an error code if an error occurs (SQLITE_NOMEM is possible). -** Otherwise return SQLITE_OK. If there is no next entry on the node -** (e.g. because the current entry is the last) set NodeReader->aNode to -** NULL to indicate EOF. Otherwise, populate the NodeReader structure output -** variables for the new entry. -*/ -static int nodeReaderNext(NodeReader *p){ - int bFirst = (p->term.n==0); /* True for first term on the node */ - int nPrefix = 0; /* Bytes to copy from previous term */ - int nSuffix = 0; /* Bytes to append to the prefix */ - int rc = SQLITE_OK; /* Return code */ - - assert( p->aNode ); - if( p->iChild && bFirst==0 ) p->iChild++; - if( p->iOff>=p->nNode ){ - /* EOF */ - p->aNode = 0; - }else{ - if( bFirst==0 ){ - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix); - } - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); - - if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){ - return FTS_CORRUPT_VTAB; - } - blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); - if( rc==SQLITE_OK ){ - memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); - p->term.n = nPrefix+nSuffix; - p->iOff += nSuffix; - if( p->iChild==0 ){ - p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); - if( (p->nNode-p->iOff)nDoclist ){ - return FTS_CORRUPT_VTAB; - } - p->aDoclist = &p->aNode[p->iOff]; - p->iOff += p->nDoclist; - } - } - } - - assert( p->iOff<=p->nNode ); - return rc; -} - -/* -** Release all dynamic resources held by node-reader object *p. -*/ -static void nodeReaderRelease(NodeReader *p){ - sqlite3_free(p->term.a); -} - -/* -** Initialize a node-reader object to read the node in buffer aNode/nNode. -** -** If successful, SQLITE_OK is returned and the NodeReader object set to -** point to the first entry on the node (if any). Otherwise, an SQLite -** error code is returned. -*/ -static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ - memset(p, 0, sizeof(NodeReader)); - p->aNode = aNode; - p->nNode = nNode; - - /* Figure out if this is a leaf or an internal node. */ - if( p->aNode[0] ){ - /* An internal node. */ - p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); - }else{ - p->iOff = 1; - } - - return nodeReaderNext(p); -} - -/* -** This function is called while writing an FTS segment each time a leaf o -** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed -** to be greater than the largest key on the node just written, but smaller -** than or equal to the first key that will be written to the next leaf -** node. -** -** The block id of the leaf node just written to disk may be found in -** (pWriter->aNodeWriter[0].iBlock) when this function is called. -*/ -static int fts3IncrmergePush( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - const char *zTerm, /* Term to write to internal node */ - int nTerm /* Bytes at zTerm */ -){ - sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock; - int iLayer; - - assert( nTerm>0 ); - for(iLayer=1; ALWAYS(iLayeraNodeWriter[iLayer]; - int rc = SQLITE_OK; - int nPrefix; - int nSuffix; - int nSpace; - - /* Figure out how much space the key will consume if it is written to - ** the current node of layer iLayer. Due to the prefix compression, - ** the space required changes depending on which node the key is to - ** be added to. */ - nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - nSpace = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - - if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ - /* If the current node of layer iLayer contains zero keys, or if adding - ** the key to it will not cause it to grow to larger than nNodeSize - ** bytes in size, write the key here. */ - - Blob *pBlk = &pNode->block; - if( pBlk->n==0 ){ - blobGrowBuffer(pBlk, p->nNodeSize, &rc); - if( rc==SQLITE_OK ){ - pBlk->a[0] = (char)iLayer; - pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr); - } - } - blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc); - blobGrowBuffer(&pNode->key, nTerm, &rc); - - if( rc==SQLITE_OK ){ - if( pNode->key.n ){ - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); - } - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); - memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); - pBlk->n += nSuffix; - - memcpy(pNode->key.a, zTerm, nTerm); - pNode->key.n = nTerm; - } - }else{ - /* Otherwise, flush the current node of layer iLayer to disk. - ** Then allocate a new, empty sibling node. The key will be written - ** into the parent of this node. */ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - - assert( pNode->block.nAlloc>=p->nNodeSize ); - pNode->block.a[0] = (char)iLayer; - pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1); - - iNextPtr = pNode->iBlock; - pNode->iBlock++; - pNode->key.n = 0; - } - - if( rc!=SQLITE_OK || iNextPtr==0 ) return rc; - iPtr = iNextPtr; - } - - assert( 0 ); - return 0; -} - -/* -** Append a term and (optionally) doclist to the FTS segment node currently -** stored in blob *pNode. The node need not contain any terms, but the -** header must be written before this function is called. -** -** A node header is a single 0x00 byte for a leaf node, or a height varint -** followed by the left-hand-child varint for an internal node. -** -** The term to be appended is passed via arguments zTerm/nTerm. For a -** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal -** node, both aDoclist and nDoclist must be passed 0. -** -** If the size of the value in blob pPrev is zero, then this is the first -** term written to the node. Otherwise, pPrev contains a copy of the -** previous term. Before this function returns, it is updated to contain a -** copy of zTerm/nTerm. -** -** It is assumed that the buffer associated with pNode is already large -** enough to accommodate the new entry. The buffer associated with pPrev -** is extended by this function if requrired. -** -** If an error (i.e. OOM condition) occurs, an SQLite error code is -** returned. Otherwise, SQLITE_OK. -*/ -static int fts3AppendToNode( - Blob *pNode, /* Current node image to append to */ - Blob *pPrev, /* Buffer containing previous term written */ - const char *zTerm, /* New term to write */ - int nTerm, /* Size of zTerm in bytes */ - const char *aDoclist, /* Doclist (or NULL) to write */ - int nDoclist /* Size of aDoclist in bytes */ -){ - int rc = SQLITE_OK; /* Return code */ - int bFirst = (pPrev->n==0); /* True if this is the first term written */ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - - /* Node must have already been started. There must be a doclist for a - ** leaf node, and there must not be a doclist for an internal node. */ - assert( pNode->n>0 ); - assert( (pNode->a[0]=='\0')==(aDoclist!=0) ); - - blobGrowBuffer(pPrev, nTerm, &rc); - if( rc!=SQLITE_OK ) return rc; - - nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - memcpy(pPrev->a, zTerm, nTerm); - pPrev->n = nTerm; - - if( bFirst==0 ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix); - } - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix); - memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix); - pNode->n += nSuffix; - - if( aDoclist ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist); - memcpy(&pNode->a[pNode->n], aDoclist, nDoclist); - pNode->n += nDoclist; - } - - assert( pNode->n<=pNode->nAlloc ); - - return SQLITE_OK; -} - -/* -** Append the current term and doclist pointed to by cursor pCsr to the -** appendable b-tree segment opened for writing by pWriter. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int fts3IncrmergeAppend( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */ -){ - const char *zTerm = pCsr->zTerm; - int nTerm = pCsr->nTerm; - const char *aDoclist = pCsr->aDoclist; - int nDoclist = pCsr->nDoclist; - int rc = SQLITE_OK; /* Return code */ - int nSpace; /* Total space in bytes required on leaf */ - int nPrefix; /* Size of prefix shared with previous term */ - int nSuffix; /* Size of suffix (nTerm - nPrefix) */ - NodeWriter *pLeaf; /* Object used to write leaf nodes */ - - pLeaf = &pWriter->aNodeWriter[0]; - nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - - nSpace = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - - /* If the current block is not empty, and if adding this term/doclist - ** to the current block would make it larger than Fts3Table.nNodeSize - ** bytes, write this block out to the database. */ - if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ - rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); - pWriter->nWork++; - - /* Add the current term to the parent node. The term added to the - ** parent must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pLeaf->key), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - if( rc==SQLITE_OK ){ - rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1); - } - - /* Advance to the next output block */ - pLeaf->iBlock++; - pLeaf->key.n = 0; - pLeaf->block.n = 0; - - nSuffix = nTerm; - nSpace = 1; - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - } - - pWriter->nLeafData += nSpace; - blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); - if( rc==SQLITE_OK ){ - if( pLeaf->block.n==0 ){ - pLeaf->block.n = 1; - pLeaf->block.a[0] = '\0'; - } - rc = fts3AppendToNode( - &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist - ); - } - - return rc; -} - -/* -** This function is called to release all dynamic resources held by the -** merge-writer object pWriter, and if no error has occurred, to flush -** all outstanding node buffers held by pWriter to disk. -** -** If *pRc is not SQLITE_OK when this function is called, then no attempt -** is made to write any data to disk. Instead, this function serves only -** to release outstanding resources. -** -** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while -** flushing buffers to disk, *pRc is set to an SQLite error code before -** returning. -*/ -static void fts3IncrmergeRelease( - Fts3Table *p, /* FTS3 table handle */ - IncrmergeWriter *pWriter, /* Merge-writer object */ - int *pRc /* IN/OUT: Error code */ -){ - int i; /* Used to iterate through non-root layers */ - int iRoot; /* Index of root in pWriter->aNodeWriter */ - NodeWriter *pRoot; /* NodeWriter for root node */ - int rc = *pRc; /* Error code */ - - /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment - ** root node. If the segment fits entirely on a single leaf node, iRoot - ** will be set to 0. If the root node is the parent of the leaves, iRoot - ** will be 1. And so on. */ - for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ - NodeWriter *pNode = &pWriter->aNodeWriter[iRoot]; - if( pNode->block.n>0 ) break; - assert( *pRc || pNode->block.nAlloc==0 ); - assert( *pRc || pNode->key.nAlloc==0 ); - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Empty output segment. This is a no-op. */ - if( iRoot<0 ) return; - - /* The entire output segment fits on a single node. Normally, this means - ** the node would be stored as a blob in the "root" column of the %_segdir - ** table. However, this is not permitted in this case. The problem is that - ** space has already been reserved in the %_segments table, and so the - ** start_block and end_block fields of the %_segdir table must be populated. - ** And, by design or by accident, released versions of FTS cannot handle - ** segments that fit entirely on the root node with start_block!=0. - ** - ** Instead, create a synthetic root node that contains nothing but a - ** pointer to the single content node. So that the segment consists of a - ** single leaf and a single interior (root) node. - ** - ** Todo: Better might be to defer allocating space in the %_segments - ** table until we are sure it is needed. - */ - if( iRoot==0 ){ - Blob *pBlock = &pWriter->aNodeWriter[1].block; - blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc); - if( rc==SQLITE_OK ){ - pBlock->a[0] = 0x01; - pBlock->n = 1 + sqlite3Fts3PutVarint( - &pBlock->a[1], pWriter->aNodeWriter[0].iBlock - ); - } - iRoot = 1; - } - pRoot = &pWriter->aNodeWriter[iRoot]; - - /* Flush all currently outstanding nodes to disk. */ - for(i=0; iaNodeWriter[i]; - if( pNode->block.n>0 && rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - } - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Write the %_segdir record. */ - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, - pWriter->iAbsLevel+1, /* level */ - pWriter->iIdx, /* idx */ - pWriter->iStart, /* start_block */ - pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ - pWriter->iEnd, /* end_block */ - (pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */ - pRoot->block.a, pRoot->block.n /* root */ - ); - } - sqlite3_free(pRoot->block.a); - sqlite3_free(pRoot->key.a); - - *pRc = rc; -} - -/* -** Compare the term in buffer zLhs (size in bytes nLhs) with that in -** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of -** the other, it is considered to be smaller than the other. -** -** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve -** if it is greater. -*/ -static int fts3TermCmp( - const char *zLhs, int nLhs, /* LHS of comparison */ - const char *zRhs, int nRhs /* RHS of comparison */ -){ - int nCmp = MIN(nLhs, nRhs); - int res; - - res = memcmp(zLhs, zRhs, nCmp); - if( res==0 ) res = nLhs - nRhs; - - return res; -} - - -/* -** Query to see if the entry in the %_segments table with blockid iEnd is -** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before -** returning. Otherwise, set *pbRes to 0. -** -** Or, if an error occurs while querying the database, return an SQLite -** error code. The final value of *pbRes is undefined in this case. -** -** This is used to test if a segment is an "appendable" segment. If it -** is, then a NULL entry has been inserted into the %_segments table -** with blockid %_segdir.end_block. -*/ -static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){ - int bRes = 0; /* Result to set *pbRes to */ - sqlite3_stmt *pCheck = 0; /* Statement to query database with */ - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck, 1, iEnd); - if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; - rc = sqlite3_reset(pCheck); - } - - *pbRes = bRes; - return rc; -} - -/* -** This function is called when initializing an incremental-merge operation. -** It checks if the existing segment with index value iIdx at absolute level -** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the -** merge-writer object *pWriter is initialized to write to it. -** -** An existing segment can be appended to by an incremental merge if: -** -** * It was initially created as an appendable segment (with all required -** space pre-allocated), and -** -** * The first key read from the input (arguments zKey and nKey) is -** greater than the largest key currently stored in the potential -** output segment. -*/ -static int fts3IncrmergeLoad( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of candidate output segment */ - const char *zKey, /* First key to write */ - int nKey, /* Number of bytes in nKey */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return code */ - sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0); - if( rc==SQLITE_OK ){ - sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */ - sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */ - sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */ - const char *aRoot = 0; /* Pointer to %_segdir.root buffer */ - int nRoot = 0; /* Size of aRoot[] in bytes */ - int rc2; /* Return code from sqlite3_reset() */ - int bAppendable = 0; /* Set to true if segment is appendable */ - - /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */ - sqlite3_bind_int64(pSelect, 1, iAbsLevel+1); - sqlite3_bind_int(pSelect, 2, iIdx); - if( sqlite3_step(pSelect)==SQLITE_ROW ){ - iStart = sqlite3_column_int64(pSelect, 1); - iLeafEnd = sqlite3_column_int64(pSelect, 2); - fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData); - if( pWriter->nLeafData<0 ){ - pWriter->nLeafData = pWriter->nLeafData * -1; - } - pWriter->bNoLeafData = (pWriter->nLeafData==0); - nRoot = sqlite3_column_bytes(pSelect, 4); - aRoot = sqlite3_column_blob(pSelect, 4); - }else{ - return sqlite3_reset(pSelect); - } - - /* Check for the zero-length marker in the %_segments table */ - rc = fts3IsAppendable(p, iEnd, &bAppendable); - - /* Check that zKey/nKey is larger than the largest key the candidate */ - if( rc==SQLITE_OK && bAppendable ){ - char *aLeaf = 0; - int nLeaf = 0; - - rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); - if( rc==SQLITE_OK ){ - NodeReader reader; - for(rc = nodeReaderInit(&reader, aLeaf, nLeaf); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - assert( reader.aNode ); - } - if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){ - bAppendable = 0; - } - nodeReaderRelease(&reader); - } - sqlite3_free(aLeaf); - } - - if( rc==SQLITE_OK && bAppendable ){ - /* It is possible to append to this segment. Set up the IncrmergeWriter - ** object to do so. */ - int i; - int nHeight = (int)aRoot[0]; - NodeWriter *pNode; - - pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; - pWriter->iStart = iStart; - pWriter->iEnd = iEnd; - pWriter->iAbsLevel = iAbsLevel; - pWriter->iIdx = iIdx; - - for(i=nHeight+1; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - - pNode = &pWriter->aNodeWriter[nHeight]; - pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; - blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aRoot, nRoot); - pNode->block.n = nRoot; - } - - for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ - NodeReader reader; - pNode = &pWriter->aNodeWriter[i]; - - rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); - blobGrowBuffer(&pNode->key, reader.term.n, &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->key.a, reader.term.a, reader.term.n); - pNode->key.n = reader.term.n; - if( i>0 ){ - char *aBlock = 0; - int nBlock = 0; - pNode = &pWriter->aNodeWriter[i-1]; - pNode->iBlock = reader.iChild; - rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0); - blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aBlock, nBlock); - pNode->block.n = nBlock; - } - sqlite3_free(aBlock); - } - } - nodeReaderRelease(&reader); - } - } - - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** Determine the largest segment index value that exists within absolute -** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus -** one before returning SQLITE_OK. Or, if there are no segments at all -** within level iAbsLevel, set *piIdx to zero. -** -** If an error occurs, return an SQLite error code. The final value of -** *piIdx is undefined in this case. -*/ -static int fts3IncrmergeOutputIdx( - Fts3Table *p, /* FTS Table handle */ - sqlite3_int64 iAbsLevel, /* Absolute index of input segments */ - int *piIdx /* OUT: Next free index at iAbsLevel+1 */ -){ - int rc; - sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */ - - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1); - sqlite3_step(pOutputIdx); - *piIdx = sqlite3_column_int(pOutputIdx, 0); - rc = sqlite3_reset(pOutputIdx); - } - - return rc; -} - -/* -** Allocate an appendable output segment on absolute level iAbsLevel+1 -** with idx value iIdx. -** -** In the %_segdir table, a segment is defined by the values in three -** columns: -** -** start_block -** leaves_end_block -** end_block -** -** When an appendable segment is allocated, it is estimated that the -** maximum number of leaf blocks that may be required is the sum of the -** number of leaf blocks consumed by the input segments, plus the number -** of input segments, multiplied by two. This value is stored in stack -** variable nLeafEst. -** -** A total of 16*nLeafEst blocks are allocated when an appendable segment -** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous -** array of leaf nodes starts at the first block allocated. The array -** of interior nodes that are parents of the leaf nodes start at block -** (start_block + (1 + end_block - start_block) / 16). And so on. -** -** In the actual code below, the value "16" is replaced with the -** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT. -*/ -static int fts3IncrmergeWriter( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of new output segment */ - Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return Code */ - int i; /* Iterator variable */ - int nLeafEst = 0; /* Blocks allocated for leaf nodes */ - sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ - sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ - - /* Calculate nLeafEst. */ - rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); - sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); - if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ - nLeafEst = sqlite3_column_int(pLeafEst, 0); - } - rc = sqlite3_reset(pLeafEst); - } - if( rc!=SQLITE_OK ) return rc; - - /* Calculate the first block to use in the output segment */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){ - pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0); - pWriter->iEnd = pWriter->iStart - 1; - pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT; - } - rc = sqlite3_reset(pFirstBlock); - } - if( rc!=SQLITE_OK ) return rc; - - /* Insert the marker in the %_segments table to make sure nobody tries - ** to steal the space just allocated. This is also used to identify - ** appendable segments. */ - rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); - if( rc!=SQLITE_OK ) return rc; - - pWriter->iAbsLevel = iAbsLevel; - pWriter->nLeafEst = nLeafEst; - pWriter->iIdx = iIdx; - - /* Set up the array of NodeWriter objects */ - for(i=0; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - return SQLITE_OK; -} - -/* -** Remove an entry from the %_segdir table. This involves running the -** following two statements: -** -** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx -** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx -** -** The DELETE statement removes the specific %_segdir level. The UPDATE -** statement ensures that the remaining segments have contiguously allocated -** idx values. -*/ -static int fts3RemoveSegdirEntry( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to delete from */ - int iIdx /* Index of %_segdir entry to delete */ -){ - int rc; /* Return code */ - sqlite3_stmt *pDelete = 0; /* DELETE statement */ - - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, iAbsLevel); - sqlite3_bind_int(pDelete, 2, iIdx); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** One or more segments have just been removed from absolute level iAbsLevel. -** Update the 'idx' values of the remaining segments in the level so that -** the idx values are a contiguous sequence starting from 0. -*/ -static int fts3RepackSegdirLevel( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel /* Absolute level to repack */ -){ - int rc; /* Return code */ - int *aIdx = 0; /* Array of remaining idx values */ - int nIdx = 0; /* Valid entries in aIdx[] */ - int nAlloc = 0; /* Allocated size of aIdx[] */ - int i; /* Iterator variable */ - sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */ - sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */ - - rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int64(pSelect, 1, iAbsLevel); - while( SQLITE_ROW==sqlite3_step(pSelect) ){ - if( nIdx>=nAlloc ){ - int *aNew; - nAlloc += 16; - aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); - if( !aNew ){ - rc = SQLITE_NOMEM; - break; - } - aIdx = aNew; - } - aIdx[nIdx++] = sqlite3_column_int(pSelect, 0); - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0); - } - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate, 2, iAbsLevel); - } - - assert( p->bIgnoreSavepoint==0 ); - p->bIgnoreSavepoint = 1; - for(i=0; rc==SQLITE_OK && ibIgnoreSavepoint = 0; - - sqlite3_free(aIdx); - return rc; -} - -static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){ - pNode->a[0] = (char)iHeight; - if( iChild ){ - assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) ); - pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild); - }else{ - assert( pNode->nAlloc>=1 ); - pNode->n = 1; - } -} - -/* -** The first two arguments are a pointer to and the size of a segment b-tree -** node. The node may be a leaf or an internal node. -** -** This function creates a new node image in blob object *pNew by copying -** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes) -** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode. -*/ -static int fts3TruncateNode( - const char *aNode, /* Current node image */ - int nNode, /* Size of aNode in bytes */ - Blob *pNew, /* OUT: Write new node image here */ - const char *zTerm, /* Omit all terms smaller than this */ - int nTerm, /* Size of zTerm in bytes */ - sqlite3_int64 *piBlock /* OUT: Block number in next layer down */ -){ - NodeReader reader; /* Reader object */ - Blob prev = {0, 0, 0}; /* Previous term written to new node */ - int rc = SQLITE_OK; /* Return code */ - int bLeaf = aNode[0]=='\0'; /* True for a leaf node */ - - /* Allocate required output space */ - blobGrowBuffer(pNew, nNode, &rc); - if( rc!=SQLITE_OK ) return rc; - pNew->n = 0; - - /* Populate new node buffer */ - for(rc = nodeReaderInit(&reader, aNode, nNode); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - if( pNew->n==0 ){ - int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm); - if( res<0 || (bLeaf==0 && res==0) ) continue; - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - rc = fts3AppendToNode( - pNew, &prev, reader.term.a, reader.term.n, - reader.aDoclist, reader.nDoclist - ); - if( rc!=SQLITE_OK ) break; - } - if( pNew->n==0 ){ - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - assert( pNew->n<=pNew->nAlloc ); - - nodeReaderRelease(&reader); - sqlite3_free(prev.a); - return rc; -} - -/* -** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute -** level iAbsLevel. This may involve deleting entries from the %_segments -** table, and modifying existing entries in both the %_segments and %_segdir -** tables. -** -** SQLITE_OK is returned if the segment is updated successfully. Or an -** SQLite error code otherwise. -*/ -static int fts3TruncateSegment( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */ - int iIdx, /* Index within level of segment to modify */ - const char *zTerm, /* Remove terms smaller than this */ - int nTerm /* Number of bytes in buffer zTerm */ -){ - int rc = SQLITE_OK; /* Return code */ - Blob root = {0,0,0}; /* New root page image */ - Blob block = {0,0,0}; /* Buffer used for any other block */ - sqlite3_int64 iBlock = 0; /* Block id */ - sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */ - sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */ - sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0); - if( rc==SQLITE_OK ){ - int rc2; /* sqlite3_reset() return code */ - sqlite3_bind_int64(pFetch, 1, iAbsLevel); - sqlite3_bind_int(pFetch, 2, iIdx); - if( SQLITE_ROW==sqlite3_step(pFetch) ){ - const char *aRoot = sqlite3_column_blob(pFetch, 4); - int nRoot = sqlite3_column_bytes(pFetch, 4); - iOldStart = sqlite3_column_int64(pFetch, 1); - rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); - } - rc2 = sqlite3_reset(pFetch); - if( rc==SQLITE_OK ) rc = rc2; - } - - while( rc==SQLITE_OK && iBlock ){ - char *aBlock = 0; - int nBlock = 0; - iNewStart = iBlock; - - rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); - if( rc==SQLITE_OK ){ - rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, iNewStart, block.a, block.n); - } - sqlite3_free(aBlock); - } - - /* Variable iNewStart now contains the first valid leaf node. */ - if( rc==SQLITE_OK && iNewStart ){ - sqlite3_stmt *pDel = 0; - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDel, 1, iOldStart); - sqlite3_bind_int64(pDel, 2, iNewStart-1); - sqlite3_step(pDel); - rc = sqlite3_reset(pDel); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_stmt *pChomp = 0; - rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pChomp, 1, iNewStart); - sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); - sqlite3_bind_int64(pChomp, 3, iAbsLevel); - sqlite3_bind_int(pChomp, 4, iIdx); - sqlite3_step(pChomp); - rc = sqlite3_reset(pChomp); - sqlite3_bind_null(pChomp, 2); - } - } - - sqlite3_free(root.a); - sqlite3_free(block.a); - return rc; -} - -/* -** This function is called after an incrmental-merge operation has run to -** merge (or partially merge) two or more segments from absolute level -** iAbsLevel. -** -** Each input segment is either removed from the db completely (if all of -** its data was copied to the output segment by the incrmerge operation) -** or modified in place so that it no longer contains those entries that -** have been duplicated in the output segment. -*/ -static int fts3IncrmergeChomp( - Fts3Table *p, /* FTS table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level containing segments */ - Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */ - int *pnRem /* Number of segments not deleted */ -){ - int i; - int nRem = 0; - int rc = SQLITE_OK; - - for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){ - Fts3SegReader *pSeg = 0; - int j; - - /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding - ** somewhere in the pCsr->apSegment[] array. */ - for(j=0; ALWAYS(jnSegment); j++){ - pSeg = pCsr->apSegment[j]; - if( pSeg->iIdx==i ) break; - } - assert( jnSegment && pSeg->iIdx==i ); - - if( pSeg->aNode==0 ){ - /* Seg-reader is at EOF. Remove the entire input segment. */ - rc = fts3DeleteSegment(p, pSeg); - if( rc==SQLITE_OK ){ - rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx); - } - *pnRem = 0; - }else{ - /* The incremental merge did not copy all the data from this - ** segment to the upper level. The segment is modified in place - ** so that it contains no keys smaller than zTerm/nTerm. */ - const char *zTerm = pSeg->zTerm; - int nTerm = pSeg->nTerm; - rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm); - nRem++; - } - } - - if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){ - rc = fts3RepackSegdirLevel(p, iAbsLevel); - } - - *pnRem = nRem; - return rc; -} - -/* -** Store an incr-merge hint in the database. -*/ -static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pReplace = 0; - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT); - sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); - sqlite3_step(pReplace); - rc = sqlite3_reset(pReplace); - sqlite3_bind_null(pReplace, 2); - } - - return rc; -} - -/* -** Load an incr-merge hint from the database. The incr-merge hint, if one -** exists, is stored in the rowid==1 row of the %_stat table. -** -** If successful, populate blob *pHint with the value read from the %_stat -** table and return SQLITE_OK. Otherwise, if an error occurs, return an -** SQLite error code. -*/ -static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pSelect = 0; - int rc; - - pHint->n = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT); - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - const char *aHint = sqlite3_column_blob(pSelect, 0); - int nHint = sqlite3_column_bytes(pSelect, 0); - if( aHint ){ - blobGrowBuffer(pHint, nHint, &rc); - if( rc==SQLITE_OK ){ - memcpy(pHint->a, aHint, nHint); - pHint->n = nHint; - } - } - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, append an entry to the hint stored in blob *pHint. Each entry -** consists of two varints, the absolute level number of the input segments -** and the number of input segments. -** -** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs, -** set *pRc to an SQLite error code before returning. -*/ -static void fts3IncrmergeHintPush( - Blob *pHint, /* Hint blob to append to */ - i64 iAbsLevel, /* First varint to store in hint */ - int nInput, /* Second varint to store in hint */ - int *pRc /* IN/OUT: Error code */ -){ - blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc); - if( *pRc==SQLITE_OK ){ - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel); - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput); - } -} - -/* -** Read the last entry (most recently pushed) from the hint blob *pHint -** and then remove the entry. Write the two values read to *piAbsLevel and -** *pnInput before returning. -** -** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does -** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB. -*/ -static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ - const int nHint = pHint->n; - int i; - - i = pHint->n-2; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - - pHint->n = i; - i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); - i += fts3GetVarint32(&pHint->a[i], pnInput); - if( i!=nHint ) return FTS_CORRUPT_VTAB; - - return SQLITE_OK; -} - - -/* -** Attempt an incremental merge that writes nMerge leaf blocks. -** -** Incremental merges happen nMin segments at a time. The segments -** to be merged are the nMin oldest segments (the ones with the smallest -** values for the _segdir.idx field) in the highest level that contains -** at least nMin segments. Multiple merges might occur in an attempt to -** write the quota of nMerge leaf blocks. -*/ -int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ - int rc; /* Return code */ - int nRem = nMerge; /* Number of leaf pages yet to be written */ - Fts3MultiSegReader *pCsr; /* Cursor used to read input data */ - Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */ - IncrmergeWriter *pWriter; /* Writer object */ - int nSeg = 0; /* Number of input segments */ - sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */ - Blob hint = {0, 0, 0}; /* Hint read from %_stat table */ - int bDirtyHint = 0; /* True if blob 'hint' has been modified */ - - /* Allocate space for the cursor, filter and writer objects */ - const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); - if( !pWriter ) return SQLITE_NOMEM; - pFilter = (Fts3SegFilter *)&pWriter[1]; - pCsr = (Fts3MultiSegReader *)&pFilter[1]; - - rc = fts3IncrmergeHintLoad(p, &hint); - while( rc==SQLITE_OK && nRem>0 ){ - const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex; - sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */ - int bUseHint = 0; /* True if attempting to append */ - int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ - - /* Search the %_segdir table for the absolute level with the smallest - ** relative level number that contains at least nMin segments, if any. - ** If one is found, set iAbsLevel to the absolute level number and - ** nSeg to nMin. If no level with at least nMin segments can be found, - ** set nSeg to -1. - */ - rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); - sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin)); - if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ - iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - nSeg = sqlite3_column_int(pFindLevel, 1); - assert( nSeg>=2 ); - }else{ - nSeg = -1; - } - rc = sqlite3_reset(pFindLevel); - - /* If the hint read from the %_stat table is not empty, check if the - ** last entry in it specifies a relative level smaller than or equal - ** to the level identified by the block above (if any). If so, this - ** iteration of the loop will work on merging at the hinted level. - */ - if( rc==SQLITE_OK && hint.n ){ - int nHint = hint.n; - sqlite3_int64 iHintAbsLevel = 0; /* Hint level */ - int nHintSeg = 0; /* Hint number of segments */ - - rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg); - if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){ - iAbsLevel = iHintAbsLevel; - nSeg = nHintSeg; - bUseHint = 1; - bDirtyHint = 1; - }else{ - /* This undoes the effect of the HintPop() above - so that no entry - ** is removed from the hint blob. */ - hint.n = nHint; - } - } - - /* If nSeg is less that zero, then there is no level with at least - ** nMin segments and no hint in the %_stat table. No work to do. - ** Exit early in this case. */ - if( nSeg<0 ) break; - - /* Open a cursor to iterate through the contents of the oldest nSeg - ** indexes of absolute level iAbsLevel. If this cursor is opened using - ** the 'hint' parameters, it is possible that there are less than nSeg - ** segments available in level iAbsLevel. In this case, no work is - ** done on iAbsLevel - fall through to the next iteration of the loop - ** to start work on some other level. */ - memset(pWriter, 0, nAlloc); - pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; - - if( rc==SQLITE_OK ){ - rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); - assert( bUseHint==1 || bUseHint==0 ); - if( iIdx==0 || (bUseHint && iIdx==1) ){ - int bIgnore = 0; - rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore); - if( bIgnore ){ - pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY; - } - } - } - - if( rc==SQLITE_OK ){ - rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); - } - if( SQLITE_OK==rc && pCsr->nSegment==nSeg - && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) - ){ - if( bUseHint && iIdx>0 ){ - const char *zKey = pCsr->zTerm; - int nKey = pCsr->nTerm; - rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); - }else{ - rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); - } - - if( rc==SQLITE_OK && pWriter->nLeafEst ){ - fts3LogMerge(nSeg, iAbsLevel); - do { - rc = fts3IncrmergeAppend(p, pWriter, pCsr); - if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; - }while( rc==SQLITE_ROW ); - - /* Update or delete the input segments */ - if( rc==SQLITE_OK ){ - nRem -= (1 + pWriter->nWork); - rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg); - if( nSeg!=0 ){ - bDirtyHint = 1; - fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc); - } - } - } - - if( nSeg!=0 ){ - pWriter->nLeafData = pWriter->nLeafData * -1; - } - fts3IncrmergeRelease(p, pWriter, &rc); - if( nSeg==0 && pWriter->bNoLeafData==0 ){ - fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData); - } - } - - sqlite3Fts3SegReaderFinish(pCsr); - } - - /* Write the hint values into the %_stat table for the next incr-merger */ - if( bDirtyHint && rc==SQLITE_OK ){ - rc = fts3IncrmergeHintStore(p, &hint); - } - - sqlite3_free(pWriter); - sqlite3_free(hint.a); - return rc; -} - -/* -** Convert the text beginning at *pz into an integer and return -** its value. Advance *pz to point to the first character past -** the integer. -** -** This function used for parameters to merge= and incrmerge= -** commands. -*/ -static int fts3Getint(const char **pz){ - const char *z = *pz; - int i = 0; - while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0'; - *pz = z; - return i; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('merge=A,B'); -** -** A and B are integers that decode to be the number of leaf pages -** written for the merge, and the minimum number of segments on a level -** before it will be selected for a merge, respectively. -*/ -static int fts3DoIncrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing "A,B" */ -){ - int rc; - int nMin = (FTS3_MERGE_COUNT / 2); - int nMerge = 0; - const char *z = zParam; - - /* Read the first integer value */ - nMerge = fts3Getint(&z); - - /* If the first integer value is followed by a ',', read the second - ** integer value. */ - if( z[0]==',' && z[1]!='\0' ){ - z++; - nMin = fts3Getint(&z); - } - - if( z[0]!='\0' || nMin<2 ){ - rc = SQLITE_ERROR; - }else{ - rc = SQLITE_OK; - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3Incrmerge(p, nMerge, nMin); - } - sqlite3Fts3SegmentsClose(p); - } - return rc; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('automerge=X'); -** -** where X is an integer. X==0 means to turn automerge off. X!=0 means -** turn it on. The setting is persistent. -*/ -static int fts3DoAutoincrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing boolean */ -){ - int rc = SQLITE_OK; - sqlite3_stmt *pStmt = 0; - p->nAutoincrmerge = fts3Getint(&zParam); - if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){ - p->nAutoincrmerge = 8; - } - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - if( rc ) return rc; - } - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ) return rc; - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - return rc; -} - -/* -** Return a 64-bit checksum for the FTS index entry specified by the -** arguments to this function. -*/ -static u64 fts3ChecksumEntry( - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of zTerm in bytes */ - int iLangid, /* Language id for current row */ - int iIndex, /* Index (0..Fts3Table.nIndex-1) */ - i64 iDocid, /* Docid for current row. */ - int iCol, /* Column number */ - int iPos /* Position */ -){ - int i; - u64 ret = (u64)iDocid; - - ret += (ret<<3) + iLangid; - ret += (ret<<3) + iIndex; - ret += (ret<<3) + iCol; - ret += (ret<<3) + iPos; - for(i=0; inIndex-1) */ - int *pRc /* OUT: Return code */ -){ - Fts3SegFilter filter; - Fts3MultiSegReader csr; - int rc; - u64 cksum = 0; - - assert( *pRc==SQLITE_OK ); - - memset(&filter, 0, sizeof(filter)); - memset(&csr, 0, sizeof(csr)); - filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; - filter.flags |= FTS3_SEGMENT_SCAN; - - rc = sqlite3Fts3SegReaderCursor( - p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(p, &csr, &filter); - } - - if( rc==SQLITE_OK ){ - while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){ - char *pCsr = csr.aDoclist; - char *pEnd = &pCsr[csr.nDoclist]; - - i64 iDocid = 0; - i64 iCol = 0; - i64 iPos = 0; - - pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); - while( pCsriPrevLangid); - sqlite3_bind_int(pAllLangid, 2, p->nIndex); - while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int iLangid = sqlite3_column_int(pAllLangid, 0); - int i; - for(i=0; inIndex; i++){ - cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - /* This block calculates the checksum according to the %_content table */ - if( rc==SQLITE_OK ){ - sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; - sqlite3_stmt *pStmt = 0; - char *zSql; - - zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - i64 iDocid = sqlite3_column_int64(pStmt, 0); - int iLang = langidFromSelect(p, pStmt); - int iCol; - - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - if( p->abNotindexed[iCol]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); - int nText = sqlite3_column_bytes(pStmt, iCol+1); - sqlite3_tokenizer_cursor *pT = 0; - - rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); - if( rc==SQLITE_OK ){ - int i; - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, nToken, iLang, 0, iDocid, iCol, iPos - ); - for(i=1; inIndex; i++){ - if( p->aIndex[i].nPrefix<=nToken ){ - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos - ); - } - } - } - } - if( pT ) pModule->xClose(pT); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - } - } - - sqlite3_finalize(pStmt); - } - - *pbOk = (cksum1==cksum2); - return rc; -} - -/* -** Run the integrity-check. If no error occurs and the current contents of -** the FTS index are correct, return SQLITE_OK. Or, if the contents of the -** FTS index are incorrect, return SQLITE_CORRUPT_VTAB. -** -** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite -** error code. -** -** The integrity-check works as follows. For each token and indexed token -** prefix in the document set, a 64-bit checksum is calculated (by code -** in fts3ChecksumEntry()) based on the following: -** -** + The index number (0 for the main index, 1 for the first prefix -** index etc.), -** + The token (or token prefix) text itself, -** + The language-id of the row it appears in, -** + The docid of the row it appears in, -** + The column it appears in, and -** + The tokens position within that column. -** -** The checksums for all entries in the index are XORed together to create -** a single checksum for the entire index. -** -** The integrity-check code calculates the same checksum in two ways: -** -** 1. By scanning the contents of the FTS index, and -** 2. By scanning and tokenizing the content table. -** -** If the two checksums are identical, the integrity-check is deemed to have -** passed. -*/ -static int fts3DoIntegrityCheck( - Fts3Table *p /* FTS3 table handle */ -){ - int rc; - int bOk = 0; - rc = fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; - return rc; -} - -/* -** Handle a 'special' INSERT of the form: -** -** "INSERT INTO tbl(tbl) VALUES()" -** -** Argument pVal contains the result of . Currently the only -** meaningful value to insert is the text 'optimize'. -*/ -static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ - int rc; /* Return Code */ - const char *zVal = (const char *)sqlite3_value_text(pVal); - int nVal = sqlite3_value_bytes(pVal); - - if( !zVal ){ - return SQLITE_NOMEM; - }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){ - rc = fts3DoOptimize(p, 0); - }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){ - rc = fts3DoRebuild(p); - }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){ - rc = fts3DoIntegrityCheck(p); - }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){ - rc = fts3DoIncrmerge(p, &zVal[6]); - }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ - rc = fts3DoAutoincrmerge(p, &zVal[10]); -#ifdef SQLITE_TEST - }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ - p->nNodeSize = atoi(&zVal[9]); - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ - p->nMaxPendingData = atoi(&zVal[11]); - rc = SQLITE_OK; - }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){ - p->bNoIncrDoclist = atoi(&zVal[21]); - rc = SQLITE_OK; -#endif - }else{ - rc = SQLITE_ERROR; - } - - return rc; -} - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -/* -** Delete all cached deferred doclists. Deferred doclists are cached -** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function. -*/ -void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){ - fts3PendingListDelete(pDef->pList); - pDef->pList = 0; - } -} - -/* -** Free all entries in the pCsr->pDeffered list. Entries are added to -** this list using sqlite3Fts3DeferToken(). -*/ -void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - Fts3DeferredToken *pNext; - for(pDef=pCsr->pDeferred; pDef; pDef=pNext){ - pNext = pDef->pNext; - fts3PendingListDelete(pDef->pList); - sqlite3_free(pDef); - } - pCsr->pDeferred = 0; -} - -/* -** Generate deferred-doclists for all tokens in the pCsr->pDeferred list -** based on the row that pCsr currently points to. -** -** A deferred-doclist is like any other doclist with position information -** included, except that it only contains entries for a single row of the -** table, not for all rows. -*/ -int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return code */ - if( pCsr->pDeferred ){ - int i; /* Used to iterate through table columns */ - sqlite3_int64 iDocid; /* Docid of the row pCsr points to */ - Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */ - - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer *pT = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pT->pModule; - - assert( pCsr->isRequireSeek==0 ); - iDocid = sqlite3_column_int64(pCsr->pStmt, 0); - - for(i=0; inColumn && rc==SQLITE_OK; i++){ - if( p->abNotindexed[i]==0 ){ - const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); - sqlite3_tokenizer_cursor *pTC = 0; - - rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - Fts3PhraseToken *pPT = pDef->pToken; - if( (pDef->iCol>=p->nColumn || pDef->iCol==i) - && (pPT->bFirst==0 || iPos==0) - && (pPT->n==nToken || (pPT->isPrefix && pPT->nz, pPT->n)) - ){ - fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc); - } - } - } - if( pTC ) pModule->xClose(pTC); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - } - - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - if( pDef->pList ){ - rc = fts3PendingListAppendVarint(&pDef->pList, 0); - } - } - } - - return rc; -} - -int sqlite3Fts3DeferredTokenList( - Fts3DeferredToken *p, - char **ppData, - int *pnData -){ - char *pRet; - int nSkip; - sqlite3_int64 dummy; - - *ppData = 0; - *pnData = 0; - - if( p->pList==0 ){ - return SQLITE_OK; - } - - pRet = (char *)sqlite3_malloc(p->pList->nData); - if( !pRet ) return SQLITE_NOMEM; - - nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy); - *pnData = p->pList->nData - nSkip; - *ppData = pRet; - - memcpy(pRet, &p->pList->aData[nSkip], *pnData); - return SQLITE_OK; -} - -/* -** Add an entry for token pToken to the pCsr->pDeferred list. -*/ -int sqlite3Fts3DeferToken( - Fts3Cursor *pCsr, /* Fts3 table cursor */ - Fts3PhraseToken *pToken, /* Token to defer */ - int iCol /* Column that token must appear in (or -1) */ -){ - Fts3DeferredToken *pDeferred; - pDeferred = sqlite3_malloc(sizeof(*pDeferred)); - if( !pDeferred ){ - return SQLITE_NOMEM; - } - memset(pDeferred, 0, sizeof(*pDeferred)); - pDeferred->pToken = pToken; - pDeferred->pNext = pCsr->pDeferred; - pDeferred->iCol = iCol; - pCsr->pDeferred = pDeferred; - - assert( pToken->pDeferred==0 ); - pToken->pDeferred = pDeferred; - - return SQLITE_OK; -} -#endif - -/* -** SQLite value pRowid contains the rowid of a row that may or may not be -** present in the FTS3 table. If it is, delete it and adjust the contents -** of subsiduary data structures accordingly. -*/ -static int fts3DeleteByRowid( - Fts3Table *p, - sqlite3_value *pRowid, - int *pnChng, /* IN/OUT: Decrement if row is deleted */ - u32 *aSzDel -){ - int rc = SQLITE_OK; /* Return code */ - int bFound = 0; /* True if *pRowid really is in the table */ - - fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound); - if( bFound && rc==SQLITE_OK ){ - int isEmpty = 0; /* Deleting *pRowid leaves the table empty */ - rc = fts3IsEmpty(p, pRowid, &isEmpty); - if( rc==SQLITE_OK ){ - if( isEmpty ){ - /* Deleting this row means the whole table is empty. In this case - ** delete the contents of all three tables and throw away any - ** data in the pendingTerms hash table. */ - rc = fts3DeleteAll(p, 1); - *pnChng = 0; - memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2); - }else{ - *pnChng = *pnChng - 1; - if( p->zContentTbl==0 ){ - fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); - } - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid); - } - } - } - } - - return rc; -} - -/* -** This function does the work for the xUpdate method of FTS3 virtual -** tables. The schema of the virtual table being: -** -** CREATE TABLE ( -** , -**
HIDDEN, -** docid HIDDEN, -** HIDDEN -** ); -** -** -*/ -int sqlite3Fts3UpdateMethod( - sqlite3_vtab *pVtab, /* FTS3 vtab object */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return Code */ - u32 *aSzIns = 0; /* Sizes of inserted documents */ - u32 *aSzDel = 0; /* Sizes of deleted documents */ - int nChng = 0; /* Net change in number of documents */ - int bInsertDone = 0; - - /* At this point it must be known if the %_stat table exists or not. - ** So bHasStat may not be 2. */ - assert( p->bHasStat==0 || p->bHasStat==1 ); - - assert( p->pSegments==0 ); - assert( - nArg==1 /* DELETE operations */ - || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ - ); - - /* Check for a "special" INSERT operation. One of the form: - ** - ** INSERT INTO xyz(xyz) VALUES('command'); - */ - if( nArg>1 - && sqlite3_value_type(apVal[0])==SQLITE_NULL - && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL - ){ - rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); - goto update_out; - } - - if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ - rc = SQLITE_CONSTRAINT; - goto update_out; - } - - /* Allocate space to hold the change in document sizes */ - aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); - if( aSzDel==0 ){ - rc = SQLITE_NOMEM; - goto update_out; - } - aSzIns = &aSzDel[p->nColumn+1]; - memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2); - - rc = fts3Writelock(p); - if( rc!=SQLITE_OK ) goto update_out; - - /* If this is an INSERT operation, or an UPDATE that modifies the rowid - ** value, then this operation requires constraint handling. - ** - ** If the on-conflict mode is REPLACE, this means that the existing row - ** should be deleted from the database before inserting the new row. Or, - ** if the on-conflict mode is other than REPLACE, then this method must - ** detect the conflict and return SQLITE_CONSTRAINT before beginning to - ** modify the database file. - */ - if( nArg>1 && p->zContentTbl==0 ){ - /* Find the value object that holds the new rowid value. */ - sqlite3_value *pNewRowid = apVal[3+p->nColumn]; - if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){ - pNewRowid = apVal[1]; - } - - if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( - sqlite3_value_type(apVal[0])==SQLITE_NULL - || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid) - )){ - /* The new rowid is not NULL (in this case the rowid will be - ** automatically assigned and there is no chance of a conflict), and - ** the statement is either an INSERT or an UPDATE that modifies the - ** rowid column. So if the conflict mode is REPLACE, then delete any - ** existing row with rowid=pNewRowid. - ** - ** Or, if the conflict mode is not REPLACE, insert the new record into - ** the %_content table. If we hit the duplicate rowid constraint (or any - ** other error) while doing so, return immediately. - ** - ** This branch may also run if pNewRowid contains a value that cannot - ** be losslessly converted to an integer. In this case, the eventual - ** call to fts3InsertData() (either just below or further on in this - ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is - ** invoked, it will delete zero rows (since no row will have - ** docid=$pNewRowid if $pNewRowid is not an integer value). - */ - if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){ - rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel); - }else{ - rc = fts3InsertData(p, apVal, pRowid); - bInsertDone = 1; - } - } - } - if( rc!=SQLITE_OK ){ - goto update_out; - } - - /* If this is a DELETE or UPDATE operation, remove the old record. */ - if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ - assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); - rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); - } - - /* If this is an INSERT or UPDATE operation, insert the new record. */ - if( nArg>1 && rc==SQLITE_OK ){ - int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); - if( bInsertDone==0 ){ - rc = fts3InsertData(p, apVal, pRowid); - if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - if( rc==SQLITE_OK ){ - rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); - } - if( rc==SQLITE_OK ){ - assert( p->iPrevDocid==*pRowid ); - rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSzIns); - } - nChng++; - } - - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); - } - - update_out: - sqlite3_free(aSzDel); - sqlite3Fts3SegmentsClose(p); - return rc; -} - -/* -** Flush any data in the pending-terms hash table to disk. If successful, -** merge all segments in the database (including the new segment, if -** there was any data to flush) into a single segment. -*/ -int sqlite3Fts3Optimize(Fts3Table *p){ - int rc; - rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3DoOptimize(p, 1); - if( rc==SQLITE_OK || rc==SQLITE_DONE ){ - int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - if( rc2!=SQLITE_OK ) rc = rc2; - }else{ - sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0); - sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - } - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - -#endif diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/icu.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/icu.c deleted file mode 100644 index 13524ebc..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/icu.c +++ /dev/null @@ -1,553 +0,0 @@ -/* -** 2007 May 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $ -** -** This file implements an integration between the ICU library -** ("International Components for Unicode", an open-source library -** for handling unicode data) and SQLite. The integration uses -** ICU to provide the following to SQLite: -** -** * An implementation of the SQL regexp() function (and hence REGEXP -** operator) using the ICU uregex_XX() APIs. -** -** * Implementations of the SQL scalar upper() and lower() functions -** for case mapping. -** -** * Integration of ICU and SQLite collation sequences. -** -** * An implementation of the LIKE operator that uses ICU to -** provide case-independent matching. -*/ - -#if !defined(SQLITE_CORE) \ - || defined(SQLITE_ENABLE_ICU) \ - || defined(SQLITE_ENABLE_ICU_COLLATIONS) - -/* Include ICU headers */ -#include -#include -#include -#include - -#include - -#ifndef SQLITE_CORE - #include "sqlite3ext.h" - SQLITE_EXTENSION_INIT1 -#else - #include "sqlite3.h" -#endif - -/* -** This function is called when an ICU function called from within -** the implementation of an SQL scalar function returns an error. -** -** The scalar function context passed as the first argument is -** loaded with an error message based on the following two args. -*/ -static void icuFunctionError( - sqlite3_context *pCtx, /* SQLite scalar function context */ - const char *zName, /* Name of ICU function that failed */ - UErrorCode e /* Error code returned by ICU function */ -){ - char zBuf[128]; - sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); - zBuf[127] = '\0'; - sqlite3_result_error(pCtx, zBuf, -1); -} - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) - -/* -** Maximum length (in bytes) of the pattern in a LIKE or GLOB -** operator. -*/ -#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH -# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 -#endif - -/* -** Version of sqlite3_free() that is always a function, never a macro. -*/ -static void xFree(void *p){ - sqlite3_free(p); -} - -/* -** This lookup table is used to help decode the first byte of -** a multi-byte UTF8 character. It is copied here from SQLite source -** code file utf8.c. -*/ -static const unsigned char icuUtf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - -#define SQLITE_ICU_READ_UTF8(zIn, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = icuUtf8Trans1[c-0xc0]; \ - while( (*zIn & 0xc0)==0x80 ){ \ - c = (c<<6) + (0x3f & *(zIn++)); \ - } \ - } - -#define SQLITE_ICU_SKIP_UTF8(zIn) \ - assert( *zIn ); \ - if( *(zIn++)>=0xc0 ){ \ - while( (*zIn & 0xc0)==0x80 ){zIn++;} \ - } - - -/* -** Compare two UTF-8 strings for equality where the first string is -** a "LIKE" expression. Return true (1) if they are the same and -** false (0) if they are different. -*/ -static int icuLikeCompare( - const uint8_t *zPattern, /* LIKE pattern */ - const uint8_t *zString, /* The UTF-8 string to compare against */ - const UChar32 uEsc /* The escape character */ -){ - static const uint32_t MATCH_ONE = (uint32_t)'_'; - static const uint32_t MATCH_ALL = (uint32_t)'%'; - - int prevEscape = 0; /* True if the previous character was uEsc */ - - while( 1 ){ - - /* Read (and consume) the next character from the input pattern. */ - uint32_t uPattern; - SQLITE_ICU_READ_UTF8(zPattern, uPattern); - if( uPattern==0 ) break; - - /* There are now 4 possibilities: - ** - ** 1. uPattern is an unescaped match-all character "%", - ** 2. uPattern is an unescaped match-one character "_", - ** 3. uPattern is an unescaped escape character, or - ** 4. uPattern is to be handled as an ordinary character - */ - if( !prevEscape && uPattern==MATCH_ALL ){ - /* Case 1. */ - uint8_t c; - - /* Skip any MATCH_ALL or MATCH_ONE characters that follow a - ** MATCH_ALL. For each MATCH_ONE, skip one character in the - ** test string. - */ - while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){ - if( c==MATCH_ONE ){ - if( *zString==0 ) return 0; - SQLITE_ICU_SKIP_UTF8(zString); - } - zPattern++; - } - - if( *zPattern==0 ) return 1; - - while( *zString ){ - if( icuLikeCompare(zPattern, zString, uEsc) ){ - return 1; - } - SQLITE_ICU_SKIP_UTF8(zString); - } - return 0; - - }else if( !prevEscape && uPattern==MATCH_ONE ){ - /* Case 2. */ - if( *zString==0 ) return 0; - SQLITE_ICU_SKIP_UTF8(zString); - - }else if( !prevEscape && uPattern==(uint32_t)uEsc){ - /* Case 3. */ - prevEscape = 1; - - }else{ - /* Case 4. */ - uint32_t uString; - SQLITE_ICU_READ_UTF8(zString, uString); - uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT); - uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT); - if( uString!=uPattern ){ - return 0; - } - prevEscape = 0; - } - } - - return *zString==0; -} - -/* -** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: -** -** A LIKE B -** -** is implemented as like(B, A). If there is an escape character E, -** -** A LIKE B ESCAPE E -** -** is mapped to like(B, A, E). -*/ -static void icuLikeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zA = sqlite3_value_text(argv[0]); - const unsigned char *zB = sqlite3_value_text(argv[1]); - UChar32 uEsc = 0; - - /* Limit the length of the LIKE or GLOB pattern to avoid problems - ** of deep recursion and N*N behavior in patternCompare(). - */ - if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ - sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); - return; - } - - - if( argc==3 ){ - /* The escape character string must consist of a single UTF-8 character. - ** Otherwise, return an error. - */ - int nE= sqlite3_value_bytes(argv[2]); - const unsigned char *zE = sqlite3_value_text(argv[2]); - int i = 0; - if( zE==0 ) return; - U8_NEXT(zE, i, nE, uEsc); - if( i!=nE){ - sqlite3_result_error(context, - "ESCAPE expression must be a single character", -1); - return; - } - } - - if( zA && zB ){ - sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc)); - } -} - -/* -** Function to delete compiled regexp objects. Registered as -** a destructor function with sqlite3_set_auxdata(). -*/ -static void icuRegexpDelete(void *p){ - URegularExpression *pExpr = (URegularExpression *)p; - uregex_close(pExpr); -} - -/* -** Implementation of SQLite REGEXP operator. This scalar function takes -** two arguments. The first is a regular expression pattern to compile -** the second is a string to match against that pattern. If either -** argument is an SQL NULL, then NULL Is returned. Otherwise, the result -** is 1 if the string matches the pattern, or 0 otherwise. -** -** SQLite maps the regexp() function to the regexp() operator such -** that the following two are equivalent: -** -** zString REGEXP zPattern -** regexp(zPattern, zString) -** -** Uses the following ICU regexp APIs: -** -** uregex_open() -** uregex_matches() -** uregex_close() -*/ -static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - UErrorCode status = U_ZERO_ERROR; - URegularExpression *pExpr; - UBool res; - const UChar *zString = sqlite3_value_text16(apArg[1]); - - (void)nArg; /* Unused parameter */ - - /* If the left hand side of the regexp operator is NULL, - ** then the result is also NULL. - */ - if( !zString ){ - return; - } - - pExpr = sqlite3_get_auxdata(p, 0); - if( !pExpr ){ - const UChar *zPattern = sqlite3_value_text16(apArg[0]); - if( !zPattern ){ - return; - } - pExpr = uregex_open(zPattern, -1, 0, 0, &status); - - if( U_SUCCESS(status) ){ - sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete); - }else{ - assert(!pExpr); - icuFunctionError(p, "uregex_open", status); - return; - } - } - - /* Configure the text that the regular expression operates on. */ - uregex_setText(pExpr, zString, -1, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_setText", status); - return; - } - - /* Attempt the match */ - res = uregex_matches(pExpr, 0, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_matches", status); - return; - } - - /* Set the text that the regular expression operates on to a NULL - ** pointer. This is not really necessary, but it is tidier than - ** leaving the regular expression object configured with an invalid - ** pointer after this function returns. - */ - uregex_setText(pExpr, 0, 0, &status); - - /* Return 1 or 0. */ - sqlite3_result_int(p, res ? 1 : 0); -} - -/* -** Implementations of scalar functions for case mapping - upper() and -** lower(). Function upper() converts its input to upper-case (ABC). -** Function lower() converts to lower-case (abc). -** -** ICU provides two types of case mapping, "general" case mapping and -** "language specific". Refer to ICU documentation for the differences -** between the two. -** -** To utilise "general" case mapping, the upper() or lower() scalar -** functions are invoked with one argument: -** -** upper('ABC') -> 'abc' -** lower('abc') -> 'ABC' -** -** To access ICU "language specific" case mapping, upper() or lower() -** should be invoked with two arguments. The second argument is the name -** of the locale to use. Passing an empty string ("") or SQL NULL value -** as the second argument is the same as invoking the 1 argument version -** of upper() or lower(). -** -** lower('I', 'en_us') -> 'i' -** lower('I', 'tr_tr') -> '\u131' (small dotless i) -** -** http://www.icu-project.org/userguide/posix.html#case_mappings -*/ -static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - const UChar *zInput; /* Pointer to input string */ - UChar *zOutput = 0; /* Pointer to output buffer */ - int nInput; /* Size of utf-16 input string in bytes */ - int nOut; /* Size of output buffer in bytes */ - int cnt; - int bToUpper; /* True for toupper(), false for tolower() */ - UErrorCode status; - const char *zLocale = 0; - - assert(nArg==1 || nArg==2); - bToUpper = (sqlite3_user_data(p)!=0); - if( nArg==2 ){ - zLocale = (const char *)sqlite3_value_text(apArg[1]); - } - - zInput = sqlite3_value_text16(apArg[0]); - if( !zInput ){ - return; - } - nOut = nInput = sqlite3_value_bytes16(apArg[0]); - if( nOut==0 ){ - sqlite3_result_text16(p, "", 0, SQLITE_STATIC); - return; - } - - for(cnt=0; cnt<2; cnt++){ - UChar *zNew = sqlite3_realloc(zOutput, nOut); - if( zNew==0 ){ - sqlite3_free(zOutput); - sqlite3_result_error_nomem(p); - return; - } - zOutput = zNew; - status = U_ZERO_ERROR; - if( bToUpper ){ - nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); - }else{ - nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status); - } - - if( U_SUCCESS(status) ){ - sqlite3_result_text16(p, zOutput, nOut, xFree); - }else if( status==U_BUFFER_OVERFLOW_ERROR ){ - assert( cnt==0 ); - continue; - }else{ - icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status); - } - return; - } - assert( 0 ); /* Unreachable */ -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ - -/* -** Collation sequence destructor function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static void icuCollationDel(void *pCtx){ - UCollator *p = (UCollator *)pCtx; - ucol_close(p); -} - -/* -** Collation sequence comparison function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static int icuCollationColl( - void *pCtx, - int nLeft, - const void *zLeft, - int nRight, - const void *zRight -){ - UCollationResult res; - UCollator *p = (UCollator *)pCtx; - res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2); - switch( res ){ - case UCOL_LESS: return -1; - case UCOL_GREATER: return +1; - case UCOL_EQUAL: return 0; - } - assert(!"Unexpected return value from ucol_strcoll()"); - return 0; -} - -/* -** Implementation of the scalar function icu_load_collation(). -** -** This scalar function is used to add ICU collation based collation -** types to an SQLite database connection. It is intended to be called -** as follows: -** -** SELECT icu_load_collation(, ); -** -** Where is a string containing an ICU locale identifier (i.e. -** "en_AU", "tr_TR" etc.) and is the name of the -** collation sequence to create. -*/ -static void icuLoadCollation( - sqlite3_context *p, - int nArg, - sqlite3_value **apArg -){ - sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); - UErrorCode status = U_ZERO_ERROR; - const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ - const char *zName; /* SQL Collation sequence name (eg. "japanese") */ - UCollator *pUCollator; /* ICU library collation object */ - int rc; /* Return code from sqlite3_create_collation_x() */ - - assert(nArg==2); - (void)nArg; /* Unused parameter */ - zLocale = (const char *)sqlite3_value_text(apArg[0]); - zName = (const char *)sqlite3_value_text(apArg[1]); - - if( !zLocale || !zName ){ - return; - } - - pUCollator = ucol_open(zLocale, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "ucol_open", status); - return; - } - assert(p); - - rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator, - icuCollationColl, icuCollationDel - ); - if( rc!=SQLITE_OK ){ - ucol_close(pUCollator); - sqlite3_result_error(p, "Error registering collation function", -1); - } -} - -/* -** Register the ICU extension functions with database db. -*/ -int sqlite3IcuInit(sqlite3 *db){ - static const struct IcuScalar { - const char *zName; /* Function name */ - unsigned char nArg; /* Number of arguments */ - unsigned short enc; /* Optimal text encoding */ - unsigned char iContext; /* sqlite3_user_data() context */ - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } scalars[] = { - {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation}, -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) - {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, - {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, - {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, - {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, - {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ - }; - int rc = SQLITE_OK; - int i; - - for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){ - const struct IcuScalar *p = &scalars[i]; - rc = sqlite3_create_function( - db, p->zName, p->nArg, p->enc, - p->iContext ? (void*)db : (void*)0, - p->xFunc, 0, 0 - ); - } - - return rc; -} - -#if !SQLITE_CORE -#ifdef _WIN32 -__declspec(dllexport) -#endif -int sqlite3_icu_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3IcuInit(db); -} -#endif - -#endif diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/sqliteicu.h b/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/sqliteicu.h deleted file mode 100644 index 69b42f98..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/icu/sqliteicu.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -** 2008 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** ICU extension. All it does is declare the sqlite3IcuInit() interface. -*/ -#include "sqlite3.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -int sqlite3IcuInit(sqlite3 *db); - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - diff --git a/Example/Pods/WCDBOptimizedSQLCipher/ext/rbu/sqlite3rbu.c b/Example/Pods/WCDBOptimizedSQLCipher/ext/rbu/sqlite3rbu.c deleted file mode 100644 index e86606be..00000000 --- a/Example/Pods/WCDBOptimizedSQLCipher/ext/rbu/sqlite3rbu.c +++ /dev/null @@ -1,4945 +0,0 @@ -/* -** 2014 August 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** -** OVERVIEW -** -** The RBU extension requires that the RBU update be packaged as an -** SQLite database. The tables it expects to find are described in -** sqlite3rbu.h. Essentially, for each table xyz in the target database -** that the user wishes to write to, a corresponding data_xyz table is -** created in the RBU database and populated with one row for each row to -** update, insert or delete from the target table. -** -** The update proceeds in three stages: -** -** 1) The database is updated. The modified database pages are written -** to a *-oal file. A *-oal file is just like a *-wal file, except -** that it is named "-oal" instead of "-wal". -** Because regular SQLite clients do not look for file named -** "-oal", they go on using the original database in -** rollback mode while the *-oal file is being generated. -** -** During this stage RBU does not update the database by writing -** directly to the target tables. Instead it creates "imposter" -** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses -** to update each b-tree individually. All updates required by each -** b-tree are completed before moving on to the next, and all -** updates are done in sorted key order. -** -** 2) The "-oal" file is moved to the equivalent "-wal" -** location using a call to rename(2). Before doing this the RBU -** module takes an EXCLUSIVE lock on the database file, ensuring -** that there are no other active readers. -** -** Once the EXCLUSIVE lock is released, any other database readers -** detect the new *-wal file and read the database in wal mode. At -** this point they see the new version of the database - including -** the updates made as part of the RBU update. -** -** 3) The new *-wal file is checkpointed. This proceeds in the same way -** as a regular database checkpoint, except that a single frame is -** checkpointed each time sqlite3rbu_step() is called. If the RBU -** handle is closed before the entire *-wal file is checkpointed, -** the checkpoint progress is saved in the RBU database and the -** checkpoint can be resumed by another RBU client at some point in -** the future. -** -** POTENTIAL PROBLEMS -** -** The rename() call might not be portable. And RBU is not currently -** syncing the directory after renaming the file. -** -** When state is saved, any commit to the *-oal file and the commit to -** the RBU update database are not atomic. So if the power fails at the -** wrong moment they might get out of sync. As the main database will be -** committed before the RBU update database this will likely either just -** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE -** constraint violations). -** -** If some client does modify the target database mid RBU update, or some -** other error occurs, the RBU extension will keep throwing errors. It's -** not really clear how to get out of this state. The system could just -** by delete the RBU update database and *-oal file and have the device -** download the update again and start over. -** -** At present, for an UPDATE, both the new.* and old.* records are -** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all -** fields are collected. This means we're probably writing a lot more -** data to disk when saving the state of an ongoing update to the RBU -** update database than is strictly necessary. -** -*/ - -#include -#include -#include - -#include "sqlite3.h" - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) -#include "sqlite3rbu.h" - -#if defined(_WIN32_WCE) -#include "windows.h" -#endif - -/* Maximum number of prepared UPDATE statements held by this module */ -#define SQLITE_RBU_UPDATE_CACHESIZE 16 - -/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM -** to enable checksum verification. -*/ -#ifndef RBU_ENABLE_DELTA_CKSUM -# define RBU_ENABLE_DELTA_CKSUM 0 -#endif - -/* -** Swap two objects of type TYPE. -*/ -#if !defined(SQLITE_AMALGAMATION) -# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} -#endif - -/* -** The rbu_state table is used to save the state of a partially applied -** update so that it can be resumed later. The table consists of integer -** keys mapped to values as follows: -** -** RBU_STATE_STAGE: -** May be set to integer values 1, 2, 4 or 5. As follows: -** 1: the *-rbu file is currently under construction. -** 2: the *-rbu file has been constructed, but not yet moved -** to the *-wal path. -** 4: the checkpoint is underway. -** 5: the rbu update has been checkpointed. -** -** RBU_STATE_TBL: -** Only valid if STAGE==1. The target database name of the table -** currently being written. -** -** RBU_STATE_IDX: -** Only valid if STAGE==1. The target database name of the index -** currently being written, or NULL if the main table is currently being -** updated. -** -** RBU_STATE_ROW: -** Only valid if STAGE==1. Number of rows already processed for the current -** table/index. -** -** RBU_STATE_PROGRESS: -** Trbul number of sqlite3rbu_step() calls made so far as part of this -** rbu update. -** -** RBU_STATE_CKPT: -** Valid if STAGE==4. The 64-bit checksum associated with the wal-index -** header created by recovering the *-wal file. This is used to detect -** cases when another client appends frames to the *-wal file in the -** middle of an incremental checkpoint (an incremental checkpoint cannot -** be continued if this happens). -** -** RBU_STATE_COOKIE: -** Valid if STAGE==1. The current change-counter cookie value in the -** target db file. -** -** RBU_STATE_OALSZ: -** Valid if STAGE==1. The size in bytes of the *-oal file. -** -** RBU_STATE_DATATBL: -** Only valid if STAGE==1. The RBU database name of the table -** currently being read. -*/ -#define RBU_STATE_STAGE 1 -#define RBU_STATE_TBL 2 -#define RBU_STATE_IDX 3 -#define RBU_STATE_ROW 4 -#define RBU_STATE_PROGRESS 5 -#define RBU_STATE_CKPT 6 -#define RBU_STATE_COOKIE 7 -#define RBU_STATE_OALSZ 8 -#define RBU_STATE_PHASEONESTEP 9 -#define RBU_STATE_DATATBL 10 - -#define RBU_STAGE_OAL 1 -#define RBU_STAGE_MOVE 2 -#define RBU_STAGE_CAPTURE 3 -#define RBU_STAGE_CKPT 4 -#define RBU_STAGE_DONE 5 - - -#define RBU_CREATE_STATE \ - "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" - -typedef struct RbuFrame RbuFrame; -typedef struct RbuObjIter RbuObjIter; -typedef struct RbuState RbuState; -typedef struct rbu_vfs rbu_vfs; -typedef struct rbu_file rbu_file; -typedef struct RbuUpdateStmt RbuUpdateStmt; - -#if !defined(SQLITE_AMALGAMATION) -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; -typedef sqlite3_int64 i64; -#endif - -/* -** These values must match the values defined in wal.c for the equivalent -** locks. These are not magic numbers as they are part of the SQLite file -** format. -*/ -#define WAL_LOCK_WRITE 0 -#define WAL_LOCK_CKPT 1 -#define WAL_LOCK_READ0 3 - -#define SQLITE_FCNTL_RBUCNT 5149216 - -/* -** A structure to store values read from the rbu_state table in memory. -*/ -struct RbuState { - int eStage; - char *zTbl; - char *zDataTbl; - char *zIdx; - i64 iWalCksum; - int nRow; - i64 nProgress; - u32 iCookie; - i64 iOalSz; - i64 nPhaseOneStep; -}; - -struct RbuUpdateStmt { - char *zMask; /* Copy of update mask used with pUpdate */ - sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ - RbuUpdateStmt *pNext; -}; - -/* -** An iterator of this type is used to iterate through all objects in -** the target database that require updating. For each such table, the -** iterator visits, in order: -** -** * the table itself, -** * each index of the table (zero or more points to visit), and -** * a special "cleanup table" state. -** -** abIndexed: -** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, -** it points to an array of flags nTblCol elements in size. The flag is -** set for each column that is either a part of the PK or a part of an -** index. Or clear otherwise. -** -*/ -struct RbuObjIter { - sqlite3_stmt *pTblIter; /* Iterate through tables */ - sqlite3_stmt *pIdxIter; /* Index iterator */ - int nTblCol; /* Size of azTblCol[] array */ - char **azTblCol; /* Array of unquoted target column names */ - char **azTblType; /* Array of target column types */ - int *aiSrcOrder; /* src table col -> target table col */ - u8 *abTblPk; /* Array of flags, set on target PK columns */ - u8 *abNotNull; /* Array of flags, set on NOT NULL columns */ - u8 *abIndexed; /* Array of flags, set on indexed & PK cols */ - int eType; /* Table type - an RBU_PK_XXX value */ - - /* Output variables. zTbl==0 implies EOF. */ - int bCleanup; /* True in "cleanup" state */ - const char *zTbl; /* Name of target db table */ - const char *zDataTbl; /* Name of rbu db table (or null) */ - const char *zIdx; /* Name of target db index (or null) */ - int iTnum; /* Root page of current object */ - int iPkTnum; /* If eType==EXTERNAL, root of PK index */ - int bUnique; /* Current index is unique */ - int nIndex; /* Number of aux. indexes on table zTbl */ - - /* Statements created by rbuObjIterPrepareAll() */ - int nCol; /* Number of columns in current object */ - sqlite3_stmt *pSelect; /* Source data */ - sqlite3_stmt *pInsert; /* Statement for INSERT operations */ - sqlite3_stmt *pDelete; /* Statement for DELETE ops */ - sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ - - /* Last UPDATE used (for PK b-tree updates only), or NULL. */ - RbuUpdateStmt *pRbuUpdate; -}; - -/* -** Values for RbuObjIter.eType -** -** 0: Table does not exist (error) -** 1: Table has an implicit rowid. -** 2: Table has an explicit IPK column. -** 3: Table has an external PK index. -** 4: Table is WITHOUT ROWID. -** 5: Table is a virtual table. -*/ -#define RBU_PK_NOTABLE 0 -#define RBU_PK_NONE 1 -#define RBU_PK_IPK 2 -#define RBU_PK_EXTERNAL 3 -#define RBU_PK_WITHOUT_ROWID 4 -#define RBU_PK_VTAB 5 - - -/* -** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs -** one of the following operations. -*/ -#define RBU_INSERT 1 /* Insert on a main table b-tree */ -#define RBU_DELETE 2 /* Delete a row from a main table b-tree */ -#define RBU_REPLACE 3 /* Delete and then insert a row */ -#define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */ -#define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */ - -#define RBU_UPDATE 6 /* Update a row in a main table b-tree */ - -/* -** A single step of an incremental checkpoint - frame iWalFrame of the wal -** file should be copied to page iDbPage of the database file. -*/ -struct RbuFrame { - u32 iDbPage; - u32 iWalFrame; -}; - -/* -** RBU handle. -** -** nPhaseOneStep: -** If the RBU database contains an rbu_count table, this value is set to -** a running estimate of the number of b-tree operations required to -** finish populating the *-oal file. This allows the sqlite3_bp_progress() -** API to calculate the permyriadage progress of populating the *-oal file -** using the formula: -** -** permyriadage = (10000 * nProgress) / nPhaseOneStep -** -** nPhaseOneStep is initialized to the sum of: -** -** nRow * (nIndex + 1) -** -** for all source tables in the RBU database, where nRow is the number -** of rows in the source table and nIndex the number of indexes on the -** corresponding target database table. -** -** This estimate is accurate if the RBU update consists entirely of -** INSERT operations. However, it is inaccurate if: -** -** * the RBU update contains any UPDATE operations. If the PK specified -** for an UPDATE operation does not exist in the target table, then -** no b-tree operations are required on index b-trees. Or if the -** specified PK does exist, then (nIndex*2) such operations are -** required (one delete and one insert on each index b-tree). -** -** * the RBU update contains any DELETE operations for which the specified -** PK does not exist. In this case no operations are required on index -** b-trees. -** -** * the RBU update contains REPLACE operations. These are similar to -** UPDATE operations. -** -** nPhaseOneStep is updated to account for the conditions above during the -** first pass of each source table. The updated nPhaseOneStep value is -** stored in the rbu_state table if the RBU update is suspended. -*/ -struct sqlite3rbu { - int eStage; /* Value of RBU_STATE_STAGE field */ - sqlite3 *dbMain; /* target database handle */ - sqlite3 *dbRbu; /* rbu database handle */ - char *zTarget; /* Path to target db */ - char *zRbu; /* Path to rbu db */ - char *zState; /* Path to state db (or NULL if zRbu) */ - char zStateDb[5]; /* Db name for state ("stat" or "main") */ - int rc; /* Value returned by last rbu_step() call */ - char *zErrmsg; /* Error message if rc!=SQLITE_OK */ - int nStep; /* Rows processed for current object */ - int nProgress; /* Rows processed for all objects */ - RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ - const char *zVfsName; /* Name of automatically created rbu vfs */ - rbu_file *pTargetFd; /* File handle open on target db */ - int nPagePerSector; /* Pages per sector for pTargetFd */ - i64 iOalSz; - i64 nPhaseOneStep; - - /* The following state variables are used as part of the incremental - ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding - ** function rbuSetupCheckpoint() for details. */ - u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ - u32 mLock; - int nFrame; /* Entries in aFrame[] array */ - int nFrameAlloc; /* Allocated size of aFrame[] array */ - RbuFrame *aFrame; - int pgsz; - u8 *aBuf; - i64 iWalCksum; - i64 szTemp; /* Current size of all temp files in use */ - i64 szTempLimit; /* Total size limit for temp files */ - - /* Used in RBU vacuum mode only */ - int nRbu; /* Number of RBU VFS in the stack */ - rbu_file *pRbuFd; /* Fd for main db of dbRbu */ -}; - -/* -** An rbu VFS is implemented using an instance of this structure. -** -** Variable pRbu is only non-NULL for automatically created RBU VFS objects. -** It is NULL for RBU VFS objects created explicitly using -** sqlite3rbu_create_vfs(). It is used to track the total amount of temp -** space used by the RBU handle. -*/ -struct rbu_vfs { - sqlite3_vfs base; /* rbu VFS shim methods */ - sqlite3_vfs *pRealVfs; /* Underlying VFS */ - sqlite3_mutex *mutex; /* Mutex to protect pMain */ - sqlite3rbu *pRbu; /* Owner RBU object */ - rbu_file *pMain; /* List of main db files */ - rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ -}; - -/* -** Each file opened by an rbu VFS is represented by an instance of -** the following structure. -** -** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable -** "sz" is set to the current size of the database file. -*/ -struct rbu_file { - sqlite3_file base; /* sqlite3_file methods */ - sqlite3_file *pReal; /* Underlying file handle */ - rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ - sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ - i64 sz; /* Size of file in bytes (temp only) */ - - int openFlags; /* Flags this file was opened with */ - u32 iCookie; /* Cookie value for main db files */ - u8 iWriteVer; /* "write-version" value for main db files */ - u8 bNolock; /* True to fail EXCLUSIVE locks */ - - int nShm; /* Number of entries in apShm[] array */ - char **apShm; /* Array of mmap'd *-shm regions */ - char *zDel; /* Delete this when closing file */ - - const char *zWal; /* Wal filename for this main db file */ - rbu_file *pWalFd; /* Wal file descriptor for this main db */ - rbu_file *pMainNext; /* Next MAIN_DB file */ - rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ -}; - -/* -** True for an RBU vacuum handle, or false otherwise. -*/ -#define rbuIsVacuum(p) ((p)->zTarget==0) - - -/************************************************************************* -** The following three functions, found below: -** -** rbuDeltaGetInt() -** rbuDeltaChecksum() -** rbuDeltaApply() -** -** are lifted from the fossil source code (http://fossil-scm.org). They -** are used to implement the scalar SQL function rbu_fossil_delta(). -*/ - -/* -** Read bytes from *pz and convert them into a positive integer. When -** finished, leave *pz pointing to the first character past the end of -** the integer. The *pLen parameter holds the length of the string -** in *pz and is decremented once for each character in the integer. -*/ -static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){ - static const signed char zValue[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36, - -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1, - }; - unsigned int v = 0; - int c; - unsigned char *z = (unsigned char*)*pz; - unsigned char *zStart = z; - while( (c = zValue[0x7f&*(z++)])>=0 ){ - v = (v<<6) + c; - } - z--; - *pLen -= z - zStart; - *pz = (char*)z; - return v; -} - -#if RBU_ENABLE_DELTA_CKSUM -/* -** Compute a 32-bit checksum on the N-byte buffer. Return the result. -*/ -static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){ - const unsigned char *z = (const unsigned char *)zIn; - unsigned sum0 = 0; - unsigned sum1 = 0; - unsigned sum2 = 0; - unsigned sum3 = 0; - while(N >= 16){ - sum0 += ((unsigned)z[0] + z[4] + z[8] + z[12]); - sum1 += ((unsigned)z[1] + z[5] + z[9] + z[13]); - sum2 += ((unsigned)z[2] + z[6] + z[10]+ z[14]); - sum3 += ((unsigned)z[3] + z[7] + z[11]+ z[15]); - z += 16; - N -= 16; - } - while(N >= 4){ - sum0 += z[0]; - sum1 += z[1]; - sum2 += z[2]; - sum3 += z[3]; - z += 4; - N -= 4; - } - sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24); - switch(N){ - case 3: sum3 += (z[2] << 8); - case 2: sum3 += (z[1] << 16); - case 1: sum3 += (z[0] << 24); - default: ; - } - return sum3; -} -#endif - -/* -** Apply a delta. -** -** The output buffer should be big enough to hold the whole output -** file and a NUL terminator at the end. The delta_output_size() -** routine will determine this size for you. -** -** The delta string should be null-terminated. But the delta string -** may contain embedded NUL characters (if the input and output are -** binary files) so we also have to pass in the length of the delta in -** the lenDelta parameter. -** -** This function returns the size of the output file in bytes (excluding -** the final NUL terminator character). Except, if the delta string is -** malformed or intended for use with a source file other than zSrc, -** then this routine returns -1. -** -** Refer to the delta_create() documentation above for a description -** of the delta file format. -*/ -static int rbuDeltaApply( - const char *zSrc, /* The source or pattern file */ - int lenSrc, /* Length of the source file */ - const char *zDelta, /* Delta to apply to the pattern */ - int lenDelta, /* Length of the delta */ - char *zOut /* Write the output into this preallocated buffer */ -){ - unsigned int limit; - unsigned int total = 0; -#if RBU_ENABLE_DELTA_CKSUM - char *zOrigOut = zOut; -#endif - - limit = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - zDelta++; lenDelta--; - while( *zDelta && lenDelta>0 ){ - unsigned int cnt, ofst; - cnt = rbuDeltaGetInt(&zDelta, &lenDelta); - switch( zDelta[0] ){ - case '@': { - zDelta++; lenDelta--; - ofst = rbuDeltaGetInt(&zDelta, &lenDelta); - if( lenDelta>0 && zDelta[0]!=',' ){ - /* ERROR: copy command not terminated by ',' */ - return -1; - } - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: copy exceeds output file size */ - return -1; - } - if( (int)(ofst+cnt) > lenSrc ){ - /* ERROR: copy extends past end of input */ - return -1; - } - memcpy(zOut, &zSrc[ofst], cnt); - zOut += cnt; - break; - } - case ':': { - zDelta++; lenDelta--; - total += cnt; - if( total>limit ){ - /* ERROR: insert command gives an output larger than predicted */ - return -1; - } - if( (int)cnt>lenDelta ){ - /* ERROR: insert count exceeds size of delta */ - return -1; - } - memcpy(zOut, zDelta, cnt); - zOut += cnt; - zDelta += cnt; - lenDelta -= cnt; - break; - } - case ';': { - zDelta++; lenDelta--; - zOut[0] = 0; -#if RBU_ENABLE_DELTA_CKSUM - if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ - /* ERROR: bad checksum */ - return -1; - } -#endif - if( total!=limit ){ - /* ERROR: generated size does not match predicted size */ - return -1; - } - return total; - } - default: { - /* ERROR: unknown delta operator */ - return -1; - } - } - } - /* ERROR: unterminated delta */ - return -1; -} - -static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){ - int size; - size = rbuDeltaGetInt(&zDelta, &lenDelta); - if( *zDelta!='\n' ){ - /* ERROR: size integer not terminated by "\n" */ - return -1; - } - return size; -} - -/* -** End of code taken from fossil. -*************************************************************************/ - -/* -** Implementation of SQL scalar function rbu_fossil_delta(). -** -** This function applies a fossil delta patch to a blob. Exactly two -** arguments must be passed to this function. The first is the blob to -** patch and the second the patch to apply. If no error occurs, this -** function returns the patched blob. -*/ -static void rbuFossilDeltaFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *aDelta; - int nDelta; - const char *aOrig; - int nOrig; - - int nOut; - int nOut2; - char *aOut; - - assert( argc==2 ); - - nOrig = sqlite3_value_bytes(argv[0]); - aOrig = (const char*)sqlite3_value_blob(argv[0]); - nDelta = sqlite3_value_bytes(argv[1]); - aDelta = (const char*)sqlite3_value_blob(argv[1]); - - /* Figure out the size of the output */ - nOut = rbuDeltaOutputSize(aDelta, nDelta); - if( nOut<0 ){ - sqlite3_result_error(context, "corrupt fossil delta", -1); - return; - } - - aOut = sqlite3_malloc(nOut+1); - if( aOut==0 ){ - sqlite3_result_error_nomem(context); - }else{ - nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut); - if( nOut2!=nOut ){ - sqlite3_result_error(context, "corrupt fossil delta", -1); - }else{ - sqlite3_result_blob(context, aOut, nOut, sqlite3_free); - } - } -} - - -/* -** Prepare the SQL statement in buffer zSql against database handle db. -** If successful, set *ppStmt to point to the new statement and return -** SQLITE_OK. -** -** Otherwise, if an error does occur, set *ppStmt to NULL and return -** an SQLite error code. Additionally, set output variable *pzErrmsg to -** point to a buffer containing an error message. It is the responsibility -** of the caller to (eventually) free this buffer using sqlite3_free(). -*/ -static int prepareAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - const char *zSql -){ - int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - *ppStmt = 0; - } - return rc; -} - -/* -** Reset the SQL statement passed as the first argument. Return a copy -** of the value returned by sqlite3_reset(). -** -** If an error has occurred, then set *pzErrmsg to point to a buffer -** containing an error message. It is the responsibility of the caller -** to eventually free this buffer using sqlite3_free(). -*/ -static int resetAndCollectError(sqlite3_stmt *pStmt, char **pzErrmsg){ - int rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt))); - } - return rc; -} - -/* -** Unless it is NULL, argument zSql points to a buffer allocated using -** sqlite3_malloc containing an SQL statement. This function prepares the SQL -** statement against database db and frees the buffer. If statement -** compilation is successful, *ppStmt is set to point to the new statement -** handle and SQLITE_OK is returned. -** -** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code -** returned. In this case, *pzErrmsg may also be set to point to an error -** message. It is the responsibility of the caller to free this error message -** buffer using sqlite3_free(). -** -** If argument zSql is NULL, this function assumes that an OOM has occurred. -** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL. -*/ -static int prepareFreeAndCollectError( - sqlite3 *db, - sqlite3_stmt **ppStmt, - char **pzErrmsg, - char *zSql -){ - int rc; - assert( *pzErrmsg==0 ); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - *ppStmt = 0; - }else{ - rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); - sqlite3_free(zSql); - } - return rc; -} - -/* -** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated -** by an earlier call to rbuObjIterCacheTableInfo(). -*/ -static void rbuObjIterFreeCols(RbuObjIter *pIter){ - int i; - for(i=0; inTblCol; i++){ - sqlite3_free(pIter->azTblCol[i]); - sqlite3_free(pIter->azTblType[i]); - } - sqlite3_free(pIter->azTblCol); - pIter->azTblCol = 0; - pIter->azTblType = 0; - pIter->aiSrcOrder = 0; - pIter->abTblPk = 0; - pIter->abNotNull = 0; - pIter->nTblCol = 0; - pIter->eType = 0; /* Invalid value */ -} - -/* -** Finalize all statements and free all allocations that are specific to -** the current object (table/index pair). -*/ -static void rbuObjIterClearStatements(RbuObjIter *pIter){ - RbuUpdateStmt *pUp; - - sqlite3_finalize(pIter->pSelect); - sqlite3_finalize(pIter->pInsert); - sqlite3_finalize(pIter->pDelete); - sqlite3_finalize(pIter->pTmpInsert); - pUp = pIter->pRbuUpdate; - while( pUp ){ - RbuUpdateStmt *pTmp = pUp->pNext; - sqlite3_finalize(pUp->pUpdate); - sqlite3_free(pUp); - pUp = pTmp; - } - - pIter->pSelect = 0; - pIter->pInsert = 0; - pIter->pDelete = 0; - pIter->pRbuUpdate = 0; - pIter->pTmpInsert = 0; - pIter->nCol = 0; -} - -/* -** Clean up any resources allocated as part of the iterator object passed -** as the only argument. -*/ -static void rbuObjIterFinalize(RbuObjIter *pIter){ - rbuObjIterClearStatements(pIter); - sqlite3_finalize(pIter->pTblIter); - sqlite3_finalize(pIter->pIdxIter); - rbuObjIterFreeCols(pIter); - memset(pIter, 0, sizeof(RbuObjIter)); -} - -/* -** Advance the iterator to the next position. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the next entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ - int rc = p->rc; - if( rc==SQLITE_OK ){ - - /* Free any SQLite statements used while processing the previous object */ - rbuObjIterClearStatements(pIter); - if( pIter->zIdx==0 ){ - rc = sqlite3_exec(p->dbMain, - "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_update2_tr;" - "DROP TRIGGER IF EXISTS temp.rbu_delete_tr;" - , 0, 0, &p->zErrmsg - ); - } - - if( rc==SQLITE_OK ){ - if( pIter->bCleanup ){ - rbuObjIterFreeCols(pIter); - pIter->bCleanup = 0; - rc = sqlite3_step(pIter->pTblIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); - pIter->zTbl = 0; - }else{ - pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); - pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); - rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; - } - }else{ - if( pIter->zIdx==0 ){ - sqlite3_stmt *pIdx = pIter->pIdxIter; - rc = sqlite3_bind_text(pIdx, 1, pIter->zTbl, -1, SQLITE_STATIC); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_step(pIter->pIdxIter); - if( rc!=SQLITE_ROW ){ - rc = resetAndCollectError(pIter->pIdxIter, &p->zErrmsg); - pIter->bCleanup = 1; - pIter->zIdx = 0; - }else{ - pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0); - pIter->iTnum = sqlite3_column_int(pIter->pIdxIter, 1); - pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2); - rc = pIter->zIdx ? SQLITE_OK : SQLITE_NOMEM; - } - } - } - } - } - - if( rc!=SQLITE_OK ){ - rbuObjIterFinalize(pIter); - p->rc = rc; - } - return rc; -} - - -/* -** The implementation of the rbu_target_name() SQL function. This function -** accepts one or two arguments. The first argument is the name of a table - -** the name of a table in the RBU database. The second, if it is present, is 1 -** for a view or 0 for a table. -** -** For a non-vacuum RBU handle, if the table name matches the pattern: -** -** data[0-9]_ -** -** where is any sequence of 1 or more characters, is returned. -** Otherwise, if the only argument does not match the above pattern, an SQL -** NULL is returned. -** -** "data_t1" -> "t1" -** "data0123_t2" -> "t2" -** "dataAB_t3" -> NULL -** -** For an rbu vacuum handle, a copy of the first argument is returned if -** the second argument is either missing or 0 (not a view). -*/ -static void rbuTargetNameFunc( - sqlite3_context *pCtx, - int argc, - sqlite3_value **argv -){ - sqlite3rbu *p = sqlite3_user_data(pCtx); - const char *zIn; - assert( argc==1 || argc==2 ); - - zIn = (const char*)sqlite3_value_text(argv[0]); - if( zIn ){ - if( rbuIsVacuum(p) ){ - if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ - sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); - } - }else{ - if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ - int i; - for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); - if( zIn[i]=='_' && zIn[i+1] ){ - sqlite3_result_text(pCtx, &zIn[i+1], -1, SQLITE_STATIC); - } - } - } - } -} - -/* -** Initialize the iterator structure passed as the second argument. -** -** If no error occurs, SQLITE_OK is returned and the iterator is left -** pointing to the first entry. Otherwise, an error code and message is -** left in the RBU handle passed as the first argument. A copy of the -** error code is returned. -*/ -static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ - int rc; - memset(pIter, 0, sizeof(RbuObjIter)); - - rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, - sqlite3_mprintf( - "SELECT rbu_target_name(name, type='view') AS target, name " - "FROM sqlite_master " - "WHERE type IN ('table', 'view') AND target IS NOT NULL " - " %s " - "ORDER BY name" - , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : "")); - - if( rc==SQLITE_OK ){ - rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, - "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " - " FROM main.sqlite_master " - " WHERE type='index' AND tbl_name = ?" - ); - } - - pIter->bCleanup = 1; - p->rc = rc; - return rbuObjIterNext(p, pIter); -} - -/* -** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, -** an error code is stored in the RBU handle passed as the first argument. -** -** If an error has already occurred (p->rc is already set to something other -** than SQLITE_OK), then this function returns NULL without modifying the -** stored error code. In this case it still calls sqlite3_free() on any -** printf() parameters associated with %z conversions. -*/ -static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ - char *zSql = 0; - va_list ap; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ) p->rc = SQLITE_NOMEM; - }else{ - sqlite3_free(zSql); - zSql = 0; - } - va_end(ap); - return zSql; -} - -/* -** Argument zFmt is a sqlite3_mprintf() style format string. The trailing -** arguments are the usual subsitution values. This function performs -** the printf() style substitutions and executes the result as an SQL -** statement on the RBU handles database. -** -** If an error occurs, an error code and error message is stored in the -** RBU handle. If an error has already occurred when this function is -** called, it is a no-op. -*/ -static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ - va_list ap; - char *zSql; - va_start(ap, zFmt); - zSql = sqlite3_vmprintf(zFmt, ap); - if( p->rc==SQLITE_OK ){ - if( zSql==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg); - } - } - sqlite3_free(zSql); - va_end(ap); - return p->rc; -} - -/* -** Attempt to allocate and return a pointer to a zeroed block of nByte -** bytes. -** -** If an error (i.e. an OOM condition) occurs, return NULL and leave an -** error code in the rbu handle passed as the first argument. Or, if an -** error has already occurred when this function is called, return NULL -** immediately without attempting the allocation or modifying the stored -** error code. -*/ -static void *rbuMalloc(sqlite3rbu *p, int nByte){ - void *pRet = 0; - if( p->rc==SQLITE_OK ){ - assert( nByte>0 ); - pRet = sqlite3_malloc64(nByte); - if( pRet==0 ){ - p->rc = SQLITE_NOMEM; - }else{ - memset(pRet, 0, nByte); - } - } - return pRet; -} - - -/* -** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that -** there is room for at least nCol elements. If an OOM occurs, store an -** error code in the RBU handle passed as the first argument. -*/ -static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ - int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; - char **azNew; - - azNew = (char**)rbuMalloc(p, nByte); - if( azNew ){ - pIter->azTblCol = azNew; - pIter->azTblType = &azNew[nCol]; - pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol]; - pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol]; - pIter->abNotNull = (u8*)&pIter->abTblPk[nCol]; - pIter->abIndexed = (u8*)&pIter->abNotNull[nCol]; - } -} - -/* -** The first argument must be a nul-terminated string. This function -** returns a copy of the string in memory obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free this memory -** using sqlite3_free(). -** -** If an OOM condition is encountered when attempting to allocate memory, -** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, -** if the allocation succeeds, (*pRc) is left unchanged. -*/ -static char *rbuStrndup(const char *zStr, int *pRc){ - char *zRet = 0; - - assert( *pRc==SQLITE_OK ); - if( zStr ){ - size_t nCopy = strlen(zStr) + 1; - zRet = (char*)sqlite3_malloc64(nCopy); - if( zRet ){ - memcpy(zRet, zStr, nCopy); - }else{ - *pRc = SQLITE_NOMEM; - } - } - - return zRet; -} - -/* -** Finalize the statement passed as the second argument. -** -** If the sqlite3_finalize() call indicates that an error occurs, and the -** rbu handle error code is not already set, set the error code and error -** message accordingly. -*/ -static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){ - sqlite3 *db = sqlite3_db_handle(pStmt); - int rc = sqlite3_finalize(pStmt); - if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){ - p->rc = rc; - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } -} - -/* Determine the type of a table. -** -** peType is of type (int*), a pointer to an output parameter of type -** (int). This call sets the output parameter as follows, depending -** on the type of the table specified by parameters dbName and zTbl. -** -** RBU_PK_NOTABLE: No such table. -** RBU_PK_NONE: Table has an implicit rowid. -** RBU_PK_IPK: Table has an explicit IPK column. -** RBU_PK_EXTERNAL: Table has an external PK index. -** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. -** RBU_PK_VTAB: Table is a virtual table. -** -** Argument *piPk is also of type (int*), and also points to an output -** parameter. Unless the table has an external primary key index -** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, -** if the table does have an external primary key index, then *piPk -** is set to the root page number of the primary key index before -** returning. -** -** ALGORITHM: -** -** if( no entry exists in sqlite_master ){ -** return RBU_PK_NOTABLE -** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ -** return RBU_PK_VTAB -** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ -** if( the index that is the pk exists in sqlite_master ){ -** *piPK = rootpage of that index. -** return RBU_PK_EXTERNAL -** }else{ -** return RBU_PK_WITHOUT_ROWID -** } -** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ -** return RBU_PK_IPK -** }else{ -** return RBU_PK_NONE -** } -*/ -static void rbuTableType( - sqlite3rbu *p, - const char *zTab, - int *peType, - int *piTnum, - int *piPk -){ - /* - ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q) - ** 1) PRAGMA index_list = ? - ** 2) SELECT count(*) FROM sqlite_master where name=%Q - ** 3) PRAGMA table_info = ? - */ - sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; - - *peType = RBU_PK_NOTABLE; - *piPk = 0; - - assert( p->rc==SQLITE_OK ); - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, - sqlite3_mprintf( - "SELECT (sql LIKE 'create virtual%%'), rootpage" - " FROM sqlite_master" - " WHERE name=%Q", zTab - )); - if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ - /* Either an error, or no such table. */ - goto rbuTableType_end; - } - if( sqlite3_column_int(aStmt[0], 0) ){ - *peType = RBU_PK_VTAB; /* virtual table */ - goto rbuTableType_end; - } - *piTnum = sqlite3_column_int(aStmt[0], 1); - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, - sqlite3_mprintf("PRAGMA index_list=%Q",zTab) - ); - if( p->rc ) goto rbuTableType_end; - while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ - const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); - const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); - if( zOrig && zIdx && zOrig[0]=='p' ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, - sqlite3_mprintf( - "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx - )); - if( p->rc==SQLITE_OK ){ - if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ - *piPk = sqlite3_column_int(aStmt[2], 0); - *peType = RBU_PK_EXTERNAL; - }else{ - *peType = RBU_PK_WITHOUT_ROWID; - } - } - goto rbuTableType_end; - } - } - - p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info=%Q",zTab) - ); - if( p->rc==SQLITE_OK ){ - while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ - if( sqlite3_column_int(aStmt[3],5)>0 ){ - *peType = RBU_PK_IPK; /* explicit IPK column */ - goto rbuTableType_end; - } - } - *peType = RBU_PK_NONE; - } - -rbuTableType_end: { - unsigned int i; - for(i=0; iabIndexed[] array. -*/ -static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ - sqlite3_stmt *pList = 0; - int bIndex = 0; - - if( p->rc==SQLITE_OK ){ - memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); - p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - } - - pIter->nIndex = 0; - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ - const char *zIdx = (const char*)sqlite3_column_text(pList, 1); - sqlite3_stmt *pXInfo = 0; - if( zIdx==0 ) break; - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - if( iCid>=0 ) pIter->abIndexed[iCid] = 1; - } - rbuFinalize(p, pXInfo); - bIndex = 1; - pIter->nIndex++; - } - - if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ - /* "PRAGMA index_list" includes the main PK b-tree */ - pIter->nIndex--; - } - - rbuFinalize(p, pList); - if( bIndex==0 ) pIter->abIndexed = 0; -} - - -/* -** If they are not already populated, populate the pIter->azTblCol[], -** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to -** the table (not index) that the iterator currently points to. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. If -** an error does occur, an error code and error message are also left in -** the RBU handle. -*/ -static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ - if( pIter->azTblCol==0 ){ - sqlite3_stmt *pStmt = 0; - int nCol = 0; - int i; /* for() loop iterator variable */ - int bRbuRowid = 0; /* If input table has column "rbu_rowid" */ - int iOrder = 0; - int iTnum = 0; - - /* Figure out the type of table this step will deal with. */ - assert( pIter->eType==0 ); - rbuTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_NOTABLE ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); - } - if( p->rc ) return p->rc; - if( pIter->zIdx==0 ) pIter->iTnum = iTnum; - - assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK - || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID - || pIter->eType==RBU_PK_VTAB - ); - - /* Populate the azTblCol[] and nTblCol variables based on the columns - ** of the input table. Ignore any input table columns that begin with - ** "rbu_". */ - p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT * FROM '%q'", pIter->zDataTbl) - ); - if( p->rc==SQLITE_OK ){ - nCol = sqlite3_column_count(pStmt); - rbuAllocateIterArrays(p, pIter, nCol); - } - for(i=0; p->rc==SQLITE_OK && irc); - pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol; - pIter->azTblCol[pIter->nTblCol++] = zCopy; - } - else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ - bRbuRowid = 1; - } - } - sqlite3_finalize(pStmt); - pStmt = 0; - - if( p->rc==SQLITE_OK - && rbuIsVacuum(p)==0 - && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) - ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf( - "table %q %s rbu_rowid column", pIter->zDataTbl, - (bRbuRowid ? "may not have" : "requires") - ); - } - - /* Check that all non-HIDDEN columns in the destination table are also - ** present in the input table. Populate the abTblPk[], azTblType[] and - ** aiTblOrder[] arrays at the same time. */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, - sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl) - ); - } - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - const char *zName = (const char*)sqlite3_column_text(pStmt, 1); - if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */ - for(i=iOrder; inTblCol; i++){ - if( 0==strcmp(zName, pIter->azTblCol[i]) ) break; - } - if( i==pIter->nTblCol ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("column missing from %q: %s", - pIter->zDataTbl, zName - ); - }else{ - int iPk = sqlite3_column_int(pStmt, 5); - int bNotNull = sqlite3_column_int(pStmt, 3); - const char *zType = (const char*)sqlite3_column_text(pStmt, 2); - - if( i!=iOrder ){ - SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); - SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); - } - - pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); - pIter->abTblPk[iOrder] = (iPk!=0); - pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); - iOrder++; - } - } - - rbuFinalize(p, pStmt); - rbuObjIterCacheIndexedCols(p, pIter); - assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); - assert( pIter->eType!=RBU_PK_VTAB || pIter->nIndex==0 ); - } - - return p->rc; -} - -/* -** This function constructs and returns a pointer to a nul-terminated -** string containing some SQL clause or list based on one or more of the -** column names currently stored in the pIter->azTblCol[] array. -*/ -static char *rbuObjIterGetCollist( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter /* Object iterator for column names */ -){ - char *zList = 0; - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - const char *z = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z); - zSep = ", "; - } - return zList; -} - -/* -** This function is used to create a SELECT list (the list of SQL -** expressions that follows a SELECT keyword) for a SELECT statement -** used to read from an data_xxx or rbu_tmp_xxx table while updating the -** index object currently indicated by the iterator object passed as the -** second argument. A "PRAGMA index_xinfo = " statement is used -** to obtain the required information. -** -** If the index is of the following form: -** -** CREATE INDEX i1 ON t1(c, b COLLATE nocase); -** -** and "t1" is a table with an explicit INTEGER PRIMARY KEY column -** "ipk", the returned string is: -** -** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" -** -** As well as the returned string, three other malloc'd strings are -** returned via output parameters. As follows: -** -** pzImposterCols: ... -** pzImposterPk: ... -** pzWhere: ... -*/ -static char *rbuObjIterGetIndexCols( - sqlite3rbu *p, /* RBU object */ - RbuObjIter *pIter, /* Object iterator for column names */ - char **pzImposterCols, /* OUT: Columns for imposter table */ - char **pzImposterPk, /* OUT: Imposter PK clause */ - char **pzWhere, /* OUT: WHERE clause */ - int *pnBind /* OUT: Trbul number of columns */ -){ - int rc = p->rc; /* Error code */ - int rc2; /* sqlite3_finalize() return code */ - char *zRet = 0; /* String to return */ - char *zImpCols = 0; /* String to return via *pzImposterCols */ - char *zImpPK = 0; /* String to return via *pzImposterPK */ - char *zWhere = 0; /* String to return via *pzWhere */ - int nBind = 0; /* Value to return via *pnBind */ - const char *zCom = ""; /* Set to ", " later on */ - const char *zAnd = ""; /* Set to " AND " later on */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = ? */ - - if( rc==SQLITE_OK ){ - assert( p->zErrmsg==0 ); - rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) - ); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - const char *zCol; - const char *zType; - - if( iCid<0 ){ - /* An integer primary key. If the table has an explicit IPK, use - ** its name. Otherwise, use "rbu_rowid". */ - if( pIter->eType==RBU_PK_IPK ){ - int i; - for(i=0; pIter->abTblPk[i]==0; i++); - assert( inTblCol ); - zCol = pIter->azTblCol[i]; - }else if( rbuIsVacuum(p) ){ - zCol = "_rowid_"; - }else{ - zCol = "rbu_rowid"; - } - zType = "INTEGER"; - }else{ - zCol = pIter->azTblCol[iCid]; - zType = pIter->azTblType[iCid]; - } - - zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); - if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ - const char *zOrder = (bDesc ? " DESC" : ""); - zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", - zImpPK, zCom, nBind, zCol, zOrder - ); - } - zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", - zImpCols, zCom, nBind, zCol, zType, zCollate - ); - zWhere = sqlite3_mprintf( - "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol - ); - if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM; - zCom = ", "; - zAnd = " AND "; - nBind++; - } - - rc2 = sqlite3_finalize(pXInfo); - if( rc==SQLITE_OK ) rc = rc2; - - if( rc!=SQLITE_OK ){ - sqlite3_free(zRet); - sqlite3_free(zImpCols); - sqlite3_free(zImpPK); - sqlite3_free(zWhere); - zRet = 0; - zImpCols = 0; - zImpPK = 0; - zWhere = 0; - p->rc = rc; - } - - *pzImposterCols = zImpCols; - *pzImposterPk = zImpPK; - *pzWhere = zWhere; - *pnBind = nBind; - return zRet; -} - -/* -** Assuming the current table columns are "a", "b" and "c", and the zObj -** paramter is passed "old", return a string of the form: -** -** "old.a, old.b, old.b" -** -** With the column names escaped. -** -** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append -** the text ", old._rowid_" to the returned value. -*/ -static char *rbuObjIterGetOldlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zObj -){ - char *zList = 0; - if( p->rc==SQLITE_OK && pIter->abIndexed ){ - const char *zS = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abIndexed[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol); - }else{ - zList = sqlite3_mprintf("%z%sNULL", zList, zS); - } - zS = ", "; - if( zList==0 ){ - p->rc = SQLITE_NOMEM; - break; - } - } - - /* For a table with implicit rowids, append "old._rowid_" to the list. */ - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "%z, %s._rowid_", zList, zObj); - } - } - return zList; -} - -/* -** Return an expression that can be used in a WHERE clause to match the -** primary key of the current table. For example, if the table is: -** -** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)); -** -** Return the string: -** -** "b = ?1 AND c = ?2" -*/ -static char *rbuObjIterGetWhere( - sqlite3rbu *p, - RbuObjIter *pIter -){ - char *zList = 0; - if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){ - zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); - }else if( pIter->eType==RBU_PK_EXTERNAL ){ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); - zSep = " AND "; - } - } - zList = rbuMPrintf(p, - "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList - ); - - }else{ - const char *zSep = ""; - int i; - for(i=0; inTblCol; i++){ - if( pIter->abTblPk[i] ){ - const char *zCol = pIter->azTblCol[i]; - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1); - zSep = " AND "; - } - } - } - return zList; -} - -/* -** The SELECT statement iterating through the keys for the current object -** (p->objiter.pSelect) currently points to a valid row. However, there -** is something wrong with the rbu_control value in the rbu_control value -** stored in the (p->nCol+1)'th column. Set the error code and error message -** of the RBU handle to something reflecting this. -*/ -static void rbuBadControlError(sqlite3rbu *p){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("invalid rbu_control value"); -} - - -/* -** Return a nul-terminated string containing the comma separated list of -** assignments that should be included following the "SET" keyword of -** an UPDATE statement used to update the table object that the iterator -** passed as the second argument currently points to if the rbu_control -** column of the data_xxx table entry is set to zMask. -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetSetlist( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zMask -){ - char *zList = 0; - if( p->rc==SQLITE_OK ){ - int i; - - if( (int)strlen(zMask)!=pIter->nTblCol ){ - rbuBadControlError(p); - }else{ - const char *zSep = ""; - for(i=0; inTblCol; i++){ - char c = zMask[pIter->aiSrcOrder[i]]; - if( c=='x' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", - zList, zSep, pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='d' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - else if( c=='f' ){ - zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_fossil_delta(\"%w\", ?%d)", - zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 - ); - zSep = ", "; - } - } - } - } - return zList; -} - -/* -** Return a nul-terminated string consisting of nByte comma separated -** "?" expressions. For example, if nByte is 3, return a pointer to -** a buffer containing the string "?,?,?". -** -** The memory for the returned string is obtained from sqlite3_malloc(). -** It is the responsibility of the caller to eventually free it using -** sqlite3_free(). -** -** If an OOM error is encountered when allocating space for the new -** string, an error code is left in the rbu handle passed as the first -** argument and NULL is returned. Or, if an error has already occurred -** when this function is called, NULL is returned immediately, without -** attempting the allocation or modifying the stored error code. -*/ -static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ - char *zRet = 0; - int nByte = nBind*2 + 1; - - zRet = (char*)rbuMalloc(p, nByte); - if( zRet ){ - int i; - for(i=0; izIdx==0 ); - if( p->rc==SQLITE_OK ){ - const char *zSep = "PRIMARY KEY("; - sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = */ - - p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) - ); - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){ - const char *zOrig = (const char*)sqlite3_column_text(pXList,3); - if( zOrig && strcmp(zOrig, "pk")==0 ){ - const char *zIdx = (const char*)sqlite3_column_text(pXList,1); - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - break; - } - } - rbuFinalize(p, pXList); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - if( sqlite3_column_int(pXInfo, 5) ){ - /* int iCid = sqlite3_column_int(pXInfo, 0); */ - const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); - const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; - z = rbuMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); - zSep = ", "; - } - } - z = rbuMPrintf(p, "%z)", z); - rbuFinalize(p, pXInfo); - } - return z; -} - -/* -** This function creates the second imposter table used when writing to -** a table b-tree where the table has an external primary key. If the -** iterator passed as the second argument does not currently point to -** a table (not index) with an external primary key, this function is a -** no-op. -** -** Assuming the iterator does point to a table with an external PK, this -** function creates a WITHOUT ROWID imposter table named "rbu_imposter2" -** used to access that PK index. For example, if the target table is -** declared as follows: -** -** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c)); -** -** then the imposter table schema is: -** -** CREATE TABLE rbu_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID; -** -*/ -static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_EXTERNAL ){ - int tnum = pIter->iPkTnum; /* Root page of PK index */ - sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */ - const char *zIdx = 0; /* Name of PK index */ - sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */ - const char *zComma = ""; - char *zCols = 0; /* Used to build up list of table cols */ - char *zPk = 0; /* Used to build up table PK declaration */ - - /* Figure out the name of the primary key index for the current table. - ** This is needed for the argument to "PRAGMA index_xinfo". Set - ** zIdx to point to a nul-terminated string containing this name. */ - p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, - "SELECT name FROM sqlite_master WHERE rootpage = ?" - ); - if( p->rc==SQLITE_OK ){ - sqlite3_bind_int(pQuery, 1, tnum); - if( SQLITE_ROW==sqlite3_step(pQuery) ){ - zIdx = (const char*)sqlite3_column_text(pQuery, 0); - } - } - if( zIdx ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, - sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) - ); - } - rbuFinalize(p, pQuery); - - while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ - int bKey = sqlite3_column_int(pXInfo, 5); - if( bKey ){ - int iCid = sqlite3_column_int(pXInfo, 1); - int bDesc = sqlite3_column_int(pXInfo, 3); - const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, - iCid, pIter->azTblType[iCid], zCollate - ); - zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); - zComma = ", "; - } - } - zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); - rbuFinalize(p, pXInfo); - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", - zCols, zPk - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** If an error has already occurred when this function is called, it -** immediately returns zero (without doing any work). Or, if an error -** occurs during the execution of this function, it sets the error code -** in the sqlite3rbu object indicated by the first argument and returns -** zero. -** -** The iterator passed as the second argument is guaranteed to point to -** a table (not an index) when this function is called. This function -** attempts to create any imposter table required to write to the main -** table b-tree of the table before returning. Non-zero is returned if -** an imposter table are created, or zero otherwise. -** -** An imposter table is required in all cases except RBU_PK_VTAB. Only -** virtual tables are written to directly. The imposter table has the -** same schema as the actual target table (less any UNIQUE constraints). -** More precisely, the "same schema" means the same columns, types, -** collation sequences. For tables that do not have an external PRIMARY -** KEY, it also means the same PRIMARY KEY declaration. -*/ -static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ - if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){ - int tnum = pIter->iTnum; - const char *zComma = ""; - char *zSql = 0; - int iCol; - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - - for(iCol=0; p->rc==SQLITE_OK && iColnTblCol; iCol++){ - const char *zPk = ""; - const char *zCol = pIter->azTblCol[iCol]; - const char *zColl = 0; - - p->rc = sqlite3_table_column_metadata( - p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0 - ); - - if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ - /* If the target table column is an "INTEGER PRIMARY KEY", add - ** "PRIMARY KEY" to the imposter table column declaration. */ - zPk = "PRIMARY KEY "; - } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", - zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, - (pIter->abNotNull[iCol] ? " NOT NULL" : "") - ); - zComma = ", "; - } - - if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ - char *zPk = rbuWithoutRowidPK(p, pIter); - if( zPk ){ - zSql = rbuMPrintf(p, "%z, %z", zSql, zPk); - } - } - - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); - rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", - pIter->zTbl, zSql, - (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - } -} - -/* -** Prepare a statement used to insert rows into the "rbu_tmp_xxx" table. -** Specifically a statement of the form: -** -** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...); -** -** The number of bound variables is equal to the number of columns in -** the target table, plus one (for the rbu_control column), plus one more -** (for the rbu_rowid column) if the target table is an implicit IPK or -** virtual table. -*/ -static void rbuObjIterPrepareTmpInsert( - sqlite3rbu *p, - RbuObjIter *pIter, - const char *zCollist, - const char *zRbuRowid -){ - int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE); - char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid); - if( zBind ){ - assert( pIter->pTmpInsert==0 ); - p->rc = prepareFreeAndCollectError( - p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( - "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", - p->zStateDb, pIter->zDataTbl, zCollist, zRbuRowid, zBind - )); - } -} - -static void rbuTmpInsertFunc( - sqlite3_context *pCtx, - int nVal, - sqlite3_value **apVal -){ - sqlite3rbu *p = sqlite3_user_data(pCtx); - int rc = SQLITE_OK; - int i; - - assert( sqlite3_value_int(apVal[0])!=0 - || p->objiter.eType==RBU_PK_EXTERNAL - || p->objiter.eType==RBU_PK_NONE - ); - if( sqlite3_value_int(apVal[0])!=0 ){ - p->nPhaseOneStep += p->objiter.nIndex; - } - - for(i=0; rc==SQLITE_OK && iobjiter.pTmpInsert, i+1, apVal[i]); - } - if( rc==SQLITE_OK ){ - sqlite3_step(p->objiter.pTmpInsert); - rc = sqlite3_reset(p->objiter.pTmpInsert); - } - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - } -} - -/* -** Ensure that the SQLite statement handles required to update the -** target database object currently indicated by the iterator passed -** as the second argument are available. -*/ -static int rbuObjIterPrepareAll( - sqlite3rbu *p, - RbuObjIter *pIter, - int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ -){ - assert( pIter->bCleanup==0 ); - if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ - const int tnum = pIter->iTnum; - char *zCollist = 0; /* List of indexed columns */ - char **pz = &p->zErrmsg; - const char *zIdx = pIter->zIdx; - char *zLimit = 0; - - if( nOffset ){ - zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset); - if( !zLimit ) p->rc = SQLITE_NOMEM; - } - - if( zIdx ){ - const char *zTbl = pIter->zTbl; - char *zImposterCols = 0; /* Columns for imposter table */ - char *zImposterPK = 0; /* Primary key declaration for imposter */ - char *zWhere = 0; /* WHERE clause on PK columns */ - char *zBind = 0; - int nBind = 0; - - assert( pIter->eType!=RBU_PK_VTAB ); - zCollist = rbuObjIterGetIndexCols( - p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind - ); - zBind = rbuObjIterGetBindlist(p, nBind); - - /* Create the imposter table used to write to this index. */ - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum); - rbuMPrintfExec(p, p->dbMain, - "CREATE TABLE \"rbu_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID", - zTbl, zImposterCols, zImposterPK - ); - sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); - - /* Create the statement to insert index entries */ - pIter->nCol = nBind; - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pInsert, &p->zErrmsg, - sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) - ); - } - - /* And to delete index entries */ - if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError( - p->dbMain, &pIter->pDelete, &p->zErrmsg, - sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) - ); - } - - /* Create the SELECT statement to read keys in sorted order */ - if( p->rc==SQLITE_OK ){ - char *zSql; - if( rbuIsVacuum(p) ){ - zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s", - zCollist, - pIter->zDataTbl, - zCollist, zLimit - ); - }else - - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, - zCollist, zLimit - ); - }else{ - zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " - "UNION ALL " - "SELECT %s, rbu_control FROM '%q' " - "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " - "ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, - zCollist, pIter->zDataTbl, - zCollist, zLimit - ); - } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); - } - - sqlite3_free(zImposterCols); - sqlite3_free(zImposterPK); - sqlite3_free(zWhere); - sqlite3_free(zBind); - }else{ - int bRbuRowid = (pIter->eType==RBU_PK_VTAB) - ||(pIter->eType==RBU_PK_NONE) - ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)); - const char *zTbl = pIter->zTbl; /* Table this step applies to */ - const char *zWrite; /* Imposter table name */ - - char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); - char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); - - zCollist = rbuObjIterGetCollist(p, pIter); - pIter->nCol = pIter->nTblCol; - - /* Create the imposter table or tables (if required). */ - rbuCreateImposterTable(p, pIter); - rbuCreateImposterTable2(p, pIter); - zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); - - /* Create the INSERT statement to write to the target PK b-tree */ - if( p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, - sqlite3_mprintf( - "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", - zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings - ) - ); - } - - /* Create the DELETE statement to write to the target PK b-tree. - ** Because it only performs INSERT operations, this is not required for - ** an rbu vacuum handle. */ - if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ - p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, - sqlite3_mprintf( - "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere - ) - ); - } - - if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ - const char *zRbuRowid = ""; - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - zRbuRowid = ", rbu_rowid"; - } - - /* Create the rbu_tmp_xxx table and the triggers to populate it. */ - rbuMPrintfExec(p, p->dbRbu, - "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " - "SELECT *%s FROM '%q' WHERE 0;" - , p->zStateDb, pIter->zDataTbl - , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") - , pIter->zDataTbl - ); - - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(3, %s);" - "END;" - - "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(4, %s);" - "END;", - zWrite, zTbl, zOldlist, - zWrite, zTbl, zOldlist, - zWrite, zTbl, zNewlist - ); - - if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ - rbuMPrintfExec(p, p->dbMain, - "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " - "BEGIN " - " SELECT rbu_tmp_insert(0, %s);" - "END;", - zWrite, zTbl, zNewlist - ); - } - - rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); - } - - /* Create the SELECT statement to read keys from data_xxx */ - if( p->rc==SQLITE_OK ){ - const char *zRbuRowid = ""; - if( bRbuRowid ){ - zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; - } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, - sqlite3_mprintf( - "SELECT %s,%s rbu_control%s FROM '%q'%s", - zCollist, - (rbuIsVacuum(p) ? "0 AS " : ""), - zRbuRowid, - pIter->zDataTbl, zLimit - ) - ); - } - - sqlite3_free(zWhere); - sqlite3_free(zOldlist); - sqlite3_free(zNewlist); - sqlite3_free(zBindings); - } - sqlite3_free(zCollist); - sqlite3_free(zLimit); - } - - return p->rc; -} - -/* -** Set output variable *ppStmt to point to an UPDATE statement that may -** be used to update the imposter table for the main table b-tree of the -** table object that pIter currently points to, assuming that the -** rbu_control column of the data_xyz table contains zMask. -** -** If the zMask string does not specify any columns to update, then this -** is not an error. Output variable *ppStmt is set to NULL in this case. -*/ -static int rbuGetUpdateStmt( - sqlite3rbu *p, /* RBU handle */ - RbuObjIter *pIter, /* Object iterator */ - const char *zMask, /* rbu_control value ('x.x.') */ - sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */ -){ - RbuUpdateStmt **pp; - RbuUpdateStmt *pUp = 0; - int nUp = 0; - - /* In case an error occurs */ - *ppStmt = 0; - - /* Search for an existing statement. If one is found, shift it to the front - ** of the LRU queue and return immediately. Otherwise, leave nUp pointing - ** to the number of statements currently in the cache and pUp to the - ** last object in the list. */ - for(pp=&pIter->pRbuUpdate; *pp; pp=&((*pp)->pNext)){ - pUp = *pp; - if( strcmp(pUp->zMask, zMask)==0 ){ - *pp = pUp->pNext; - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - *ppStmt = pUp->pUpdate; - return SQLITE_OK; - } - nUp++; - } - assert( pUp==0 || pUp->pNext==0 ); - - if( nUp>=SQLITE_RBU_UPDATE_CACHESIZE ){ - for(pp=&pIter->pRbuUpdate; *pp!=pUp; pp=&((*pp)->pNext)); - *pp = 0; - sqlite3_finalize(pUp->pUpdate); - pUp->pUpdate = 0; - }else{ - pUp = (RbuUpdateStmt*)rbuMalloc(p, sizeof(RbuUpdateStmt)+pIter->nTblCol+1); - } - - if( pUp ){ - char *zWhere = rbuObjIterGetWhere(p, pIter); - char *zSet = rbuObjIterGetSetlist(p, pIter, zMask); - char *zUpdate = 0; - - pUp->zMask = (char*)&pUp[1]; - memcpy(pUp->zMask, zMask, pIter->nTblCol); - pUp->pNext = pIter->pRbuUpdate; - pIter->pRbuUpdate = pUp; - - if( zSet ){ - const char *zPrefix = ""; - - if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_"; - zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", - zPrefix, pIter->zTbl, zSet, zWhere - ); - p->rc = prepareFreeAndCollectError( - p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate - ); - *ppStmt = pUp->pUpdate; - } - sqlite3_free(zWhere); - sqlite3_free(zSet); - } - - return p->rc; -} - -static sqlite3 *rbuOpenDbhandle( - sqlite3rbu *p, - const char *zName, - int bUseVfs -){ - sqlite3 *db = 0; - if( p->rc==SQLITE_OK ){ - const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; - p->rc = sqlite3_open_v2(zName, &db, flags, bUseVfs ? p->zVfsName : 0); - if( p->rc ){ - p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - sqlite3_close(db); - db = 0; - } - } - return db; -} - -/* -** Free an RbuState object allocated by rbuLoadState(). -*/ -static void rbuFreeState(RbuState *p){ - if( p ){ - sqlite3_free(p->zTbl); - sqlite3_free(p->zDataTbl); - sqlite3_free(p->zIdx); - sqlite3_free(p); - } -} - -/* -** Allocate an RbuState object and load the contents of the rbu_state -** table into it. Return a pointer to the new object. It is the -** responsibility of the caller to eventually free the object using -** sqlite3_free(). -** -** If an error occurs, leave an error code and message in the rbu handle -** and return NULL. -*/ -static RbuState *rbuLoadState(sqlite3rbu *p){ - RbuState *pRet = 0; - sqlite3_stmt *pStmt = 0; - int rc; - int rc2; - - pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); - if( pRet==0 ) return 0; - - rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, - sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) - ); - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - switch( sqlite3_column_int(pStmt, 0) ){ - case RBU_STATE_STAGE: - pRet->eStage = sqlite3_column_int(pStmt, 1); - if( pRet->eStage!=RBU_STAGE_OAL - && pRet->eStage!=RBU_STAGE_MOVE - && pRet->eStage!=RBU_STAGE_CKPT - ){ - p->rc = SQLITE_CORRUPT; - } - break; - - case RBU_STATE_TBL: - pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_IDX: - pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - case RBU_STATE_ROW: - pRet->nRow = sqlite3_column_int(pStmt, 1); - break; - - case RBU_STATE_PROGRESS: - pRet->nProgress = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_CKPT: - pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_COOKIE: - pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_OALSZ: - pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_PHASEONESTEP: - pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); - break; - - case RBU_STATE_DATATBL: - pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); - break; - - default: - rc = SQLITE_CORRUPT; - break; - } - } - rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - - p->rc = rc; - return pRet; -} - - -/* -** Open the database handle and attach the RBU database as "rbu". If an -** error occurs, leave an error code and message in the RBU handle. -*/ -static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){ - assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); - assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); - - /* Open the RBU database */ - p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); - - if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ - sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); - if( p->zState==0 ){ - const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); - p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); - } - } - - /* If using separate RBU and state databases, attach the state database to - ** the RBU db handle now. */ - if( p->zState ){ - rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); - memcpy(p->zStateDb, "stat", 4); - }else{ - memcpy(p->zStateDb, "main", 4); - } - -#if 0 - if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ - p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, 0); - } -#endif - - /* If it has not already been created, create the rbu_state table */ - rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); - -#if 0 - if( rbuIsVacuum(p) ){ - if( p->rc==SQLITE_OK ){ - int rc2; - int bOk = 0; - sqlite3_stmt *pCnt = 0; - p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg, - "SELECT count(*) FROM stat.sqlite_master" - ); - if( p->rc==SQLITE_OK - && sqlite3_step(pCnt)==SQLITE_ROW - && 1==sqlite3_column_int(pCnt, 0) - ){ - bOk = 1; - } - rc2 = sqlite3_finalize(pCnt); - if( p->rc==SQLITE_OK ) p->rc = rc2; - - if( p->rc==SQLITE_OK && bOk==0 ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("invalid state database"); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); - } - } - } -#endif - - if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ - int bOpen = 0; - int rc; - p->nRbu = 0; - p->pRbuFd = 0; - rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); - if( rc!=SQLITE_NOTFOUND ) p->rc = rc; - if( p->eStage>=RBU_STAGE_MOVE ){ - bOpen = 1; - }else{ - RbuState *pState = rbuLoadState(p); - if( pState ){ - bOpen = (pState->eStage>=RBU_STAGE_MOVE); - rbuFreeState(pState); - } - } - if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1); - } - - p->eStage = 0; - if( p->rc==SQLITE_OK && p->dbMain==0 ){ - if( !rbuIsVacuum(p) ){ - p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1); - }else if( p->pRbuFd->pWalFd ){ - if( pbRetry ){ - p->pRbuFd->bNolock = 0; - sqlite3_close(p->dbRbu); - sqlite3_close(p->dbMain); - p->dbMain = 0; - p->dbRbu = 0; - *pbRetry = 1; - return; - } - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database"); - }else{ - char *zTarget; - char *zExtra = 0; - if( strlen(p->zRbu)>=5 && 0==memcmp("file:", p->zRbu, 5) ){ - zExtra = &p->zRbu[5]; - while( *zExtra ){ - if( *zExtra++=='?' ) break; - } - if( *zExtra=='\0' ) zExtra = 0; - } - - zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s", - sqlite3_db_filename(p->dbRbu, "main"), - (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra) - ); - - if( zTarget==0 ){ - p->rc = SQLITE_NOMEM; - return; - } - p->dbMain = rbuOpenDbhandle(p, zTarget, p->nRbu<=1); - sqlite3_free(zTarget); - } - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbMain, - "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_create_function(p->dbRbu, - "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 - ); - } - - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); - - /* Mark the database file just opened as an RBU target database. If - ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. - ** This is an error. */ - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); - } - - if( p->rc==SQLITE_NOTFOUND ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("rbu vfs not found"); - } -} - -/* -** This routine is a copy of the sqlite3FileSuffix3() routine from the core. -** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. -** -** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database -** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and -** if filename in z[] has a suffix (a.k.a. "extension") that is longer than -** three characters, then shorten the suffix on z[] to be the last three -** characters of the original suffix. -** -** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always -** do the suffix shortening regardless of URI parameter. -** -** Examples: -** -** test.db-journal => test.nal -** test.db-wal => test.wal -** test.db-shm => test.shm -** test.db-mj7f3319fa => test.9fa -*/ -static void rbuFileSuffix3(const char *zBase, char *z){ -#ifdef SQLITE_ENABLE_8_3_NAMES -#if SQLITE_ENABLE_8_3_NAMES<2 - if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) -#endif - { - int i, sz; - sz = (int)strlen(z)&0xffffff; - for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} - if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); - } -#endif -} - -/* -** Return the current wal-index header checksum for the target database -** as a 64-bit integer. -** -** The checksum is store in the first page of xShmMap memory as an 8-byte -** blob starting at byte offset 40. -*/ -static i64 rbuShmChecksum(sqlite3rbu *p){ - i64 iRet = 0; - if( p->rc==SQLITE_OK ){ - sqlite3_file *pDb = p->pTargetFd->pReal; - u32 volatile *ptr; - p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); - if( p->rc==SQLITE_OK ){ - iRet = ((i64)ptr[10] << 32) + ptr[11]; - } - } - return iRet; -} - -/* -** This function is called as part of initializing or reinitializing an -** incremental checkpoint. -** -** It populates the sqlite3rbu.aFrame[] array with the set of -** (wal frame -> db page) copy operations required to checkpoint the -** current wal file, and obtains the set of shm locks required to safely -** perform the copy operations directly on the file-system. -** -** If argument pState is not NULL, then the incremental checkpoint is -** being resumed. In this case, if the checksum of the wal-index-header -** following recovery is not the same as the checksum saved in the RbuState -** object, then the rbu handle is set to DONE state. This occurs if some -** other client appends a transaction to the wal file in the middle of -** an incremental checkpoint. -*/ -static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){ - - /* If pState is NULL, then the wal file may not have been opened and - ** recovered. Running a read-statement here to ensure that doing so - ** does not interfere with the "capture" process below. */ - if( pState==0 ){ - p->eStage = 0; - if( p->rc==SQLITE_OK ){ - p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0); - } - } - - /* Assuming no error has occurred, run a "restart" checkpoint with the - ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following - ** special behaviour in the rbu VFS: - ** - ** * If the exclusive shm WRITER or READ0 lock cannot be obtained, - ** the checkpoint fails with SQLITE_BUSY (normally SQLite would - ** proceed with running a passive checkpoint instead of failing). - ** - ** * Attempts to read from the *-wal file or write to the database file - ** do not perform any IO. Instead, the frame/page combinations that - ** would be read/written are recorded in the sqlite3rbu.aFrame[] - ** array. - ** - ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, - ** READ0 and CHECKPOINT locks taken as part of the checkpoint are - ** no-ops. These locks will not be released until the connection - ** is closed. - ** - ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL - ** error. - ** - ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the - ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[] - ** array populated with a set of (frame -> page) mappings. Because the - ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy - ** data from the wal file into the database file according to the - ** contents of aFrame[]. - */ - if( p->rc==SQLITE_OK ){ - int rc2; - p->eStage = RBU_STAGE_CAPTURE; - rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); - if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; - } - - if( p->rc==SQLITE_OK && p->nFrame>0 ){ - p->eStage = RBU_STAGE_CKPT; - p->nStep = (pState ? pState->nRow : 0); - p->aBuf = rbuMalloc(p, p->pgsz); - p->iWalCksum = rbuShmChecksum(p); - } - - if( p->rc==SQLITE_OK ){ - if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ - p->rc = SQLITE_DONE; - p->eStage = RBU_STAGE_DONE; - }else{ - int nSectorSize; - sqlite3_file *pDb = p->pTargetFd->pReal; - sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; - assert( p->nPagePerSector==0 ); - nSectorSize = pDb->pMethods->xSectorSize(pDb); - if( nSectorSize>p->pgsz ){ - p->nPagePerSector = nSectorSize / p->pgsz; - }else{ - p->nPagePerSector = 1; - } - - /* Call xSync() on the wal file. This causes SQLite to sync the - ** directory in which the target database and the wal file reside, in - ** case it has not been synced since the rename() call in - ** rbuMoveOalFile(). */ - p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); - } - } -} - -/* -** Called when iAmt bytes are read from offset iOff of the wal file while -** the rbu object is in capture mode. Record the frame number of the frame -** being read in the aFrame[] array. -*/ -static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ - const u32 mReq = (1<mLock!=mReq ){ - pRbu->rc = SQLITE_BUSY; - return SQLITE_INTERNAL; - } - - pRbu->pgsz = iAmt; - if( pRbu->nFrame==pRbu->nFrameAlloc ){ - int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; - RbuFrame *aNew; - aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame)); - if( aNew==0 ) return SQLITE_NOMEM; - pRbu->aFrame = aNew; - pRbu->nFrameAlloc = nNew; - } - - iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; - if( pRbu->iMaxFrame