mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Lot's of changes
This commit is contained in:
parent
4630a223b2
commit
cc75497a0c
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "submodules/sqlite.swift"]
|
||||
path = submodules/sqlite.swift
|
||||
url = https://github.com/stephencelis/SQLite.swift.git
|
@ -7,9 +7,35 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D003E4E61B38DBDB00C22CBC /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D003E4E51B38DBDB00C22CBC /* MessageView.swift */; };
|
||||
D044E15E1B2ACB9C001EE087 /* CodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D044E15D1B2ACB9C001EE087 /* CodingTests.swift */; };
|
||||
D044E1631B2AD677001EE087 /* MurMurHash32.m in Sources */ = {isa = PBXBuildFile; fileRef = D044E1621B2AD677001EE087 /* MurMurHash32.m */; };
|
||||
D044E1641B2AD718001EE087 /* MurMurHash32.h in Headers */ = {isa = PBXBuildFile; fileRef = D044E1611B2AD667001EE087 /* MurMurHash32.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D07516441B2D9CEF00AE42E0 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = D07516401B2D9CEF00AE42E0 /* sqlite3.c */; };
|
||||
D07516451B2D9CEF00AE42E0 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = D07516411B2D9CEF00AE42E0 /* sqlite3.h */; };
|
||||
D07516461B2D9CEF00AE42E0 /* sqlite3ext.h in Headers */ = {isa = PBXBuildFile; fileRef = D07516421B2D9CEF00AE42E0 /* sqlite3ext.h */; };
|
||||
D075165C1B2EC5B000AE42E0 /* module.private.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = D075165B1B2EC5B000AE42E0 /* module.private.modulemap */; };
|
||||
D075165E1B2EC5B500AE42E0 /* module.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = D075165D1B2EC5B500AE42E0 /* module.modulemap */; };
|
||||
D075166A1B2EC7FE00AE42E0 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516611B2EC7FE00AE42E0 /* Database.swift */; };
|
||||
D075166B1B2EC7FE00AE42E0 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516621B2EC7FE00AE42E0 /* Expression.swift */; };
|
||||
D075166C1B2EC7FE00AE42E0 /* FTS.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516631B2EC7FE00AE42E0 /* FTS.swift */; };
|
||||
D075166E1B2EC7FE00AE42E0 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516651B2EC7FE00AE42E0 /* Functions.swift */; };
|
||||
D075166F1B2EC7FE00AE42E0 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516661B2EC7FE00AE42E0 /* Query.swift */; };
|
||||
D07516701B2EC7FE00AE42E0 /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516671B2EC7FE00AE42E0 /* Schema.swift */; };
|
||||
D07516711B2EC7FE00AE42E0 /* Statement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516681B2EC7FE00AE42E0 /* Statement.swift */; };
|
||||
D07516721B2EC7FE00AE42E0 /* Value.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07516691B2EC7FE00AE42E0 /* Value.swift */; };
|
||||
D07516771B2EC90400AE42E0 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D07516741B2EC90400AE42E0 /* fts3_tokenizer.h */; };
|
||||
D07516781B2EC90400AE42E0 /* SQLite-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = D07516751B2EC90400AE42E0 /* SQLite-Bridging.h */; };
|
||||
D07516791B2EC90400AE42E0 /* SQLite-Bridging.m in Sources */ = {isa = PBXBuildFile; fileRef = D07516761B2EC90400AE42E0 /* SQLite-Bridging.m */; };
|
||||
D07FC7D31B4A3D6B0010B3F7 /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D07FC7D21B4A3D6B0010B3F7 /* SwiftSignalKit.framework */; };
|
||||
D0E3A7501B28A7E300A402D9 /* Postbox.h in Headers */ = {isa = PBXBuildFile; fileRef = D0E3A74F1B28A7E300A402D9 /* Postbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D0E3A7561B28A7E300A402D9 /* Postbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0E3A74A1B28A7E300A402D9 /* Postbox.framework */; };
|
||||
D0E3A75D1B28A7E300A402D9 /* PostboxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A75C1B28A7E300A402D9 /* PostboxTests.swift */; };
|
||||
D0E3A7821B28ADD000A402D9 /* Postbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A7811B28ADD000A402D9 /* Postbox.swift */; };
|
||||
D0E3A7841B28AE0900A402D9 /* Peer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A7831B28AE0900A402D9 /* Peer.swift */; };
|
||||
D0E3A7881B28AE9C00A402D9 /* Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A7871B28AE9C00A402D9 /* Coding.swift */; };
|
||||
D0E3A79E1B28B50400A402D9 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A79D1B28B50400A402D9 /* Message.swift */; };
|
||||
D0E3A7A21B28B7DC00A402D9 /* Media.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A7A11B28B7DC00A402D9 /* Media.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -23,12 +49,39 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D003E4E51B38DBDB00C22CBC /* MessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = "<group>"; };
|
||||
D044E15D1B2ACB9C001EE087 /* CodingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodingTests.swift; sourceTree = "<group>"; };
|
||||
D044E1611B2AD667001EE087 /* MurMurHash32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MurMurHash32.h; sourceTree = "<group>"; };
|
||||
D044E1621B2AD677001EE087 /* MurMurHash32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MurMurHash32.m; sourceTree = "<group>"; };
|
||||
D07516401B2D9CEF00AE42E0 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = "<group>"; };
|
||||
D07516411B2D9CEF00AE42E0 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite3.h; sourceTree = "<group>"; };
|
||||
D07516421B2D9CEF00AE42E0 /* sqlite3ext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite3ext.h; sourceTree = "<group>"; };
|
||||
D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Postbox.xcconfig; path = Postbox/Config/Postbox.xcconfig; sourceTree = "<group>"; };
|
||||
D075165B1B2EC5B000AE42E0 /* module.private.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.private.modulemap; sourceTree = "<group>"; };
|
||||
D075165D1B2EC5B500AE42E0 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D07516611B2EC7FE00AE42E0 /* Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Database.swift; path = submodules/sqlite.swift/SQLite/Database.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516621B2EC7FE00AE42E0 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = submodules/sqlite.swift/SQLite/Expression.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516631B2EC7FE00AE42E0 /* FTS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FTS.swift; path = submodules/sqlite.swift/SQLite/FTS.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516651B2EC7FE00AE42E0 /* Functions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Functions.swift; path = submodules/sqlite.swift/SQLite/Functions.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516661B2EC7FE00AE42E0 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Query.swift; path = submodules/sqlite.swift/SQLite/Query.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516671B2EC7FE00AE42E0 /* Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Schema.swift; path = submodules/sqlite.swift/SQLite/Schema.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516681B2EC7FE00AE42E0 /* Statement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Statement.swift; path = submodules/sqlite.swift/SQLite/Statement.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516691B2EC7FE00AE42E0 /* Value.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Value.swift; path = submodules/sqlite.swift/SQLite/Value.swift; sourceTree = SOURCE_ROOT; };
|
||||
D07516741B2EC90400AE42E0 /* fts3_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fts3_tokenizer.h; sourceTree = "<group>"; };
|
||||
D07516751B2EC90400AE42E0 /* SQLite-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SQLite-Bridging.h"; sourceTree = "<group>"; };
|
||||
D07516761B2EC90400AE42E0 /* SQLite-Bridging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SQLite-Bridging.m"; sourceTree = "<group>"; };
|
||||
D07FC7D21B4A3D6B0010B3F7 /* SwiftSignalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftSignalKit.framework; path = "../SSignalKit/build/Debug-iphoneos/SwiftSignalKit.framework"; sourceTree = "<group>"; };
|
||||
D0E3A74A1B28A7E300A402D9 /* Postbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Postbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0E3A74E1B28A7E300A402D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D0E3A74F1B28A7E300A402D9 /* Postbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Postbox.h; sourceTree = "<group>"; };
|
||||
D0E3A7551B28A7E300A402D9 /* PostboxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PostboxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0E3A75B1B28A7E300A402D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D0E3A75C1B28A7E300A402D9 /* PostboxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostboxTests.swift; sourceTree = "<group>"; };
|
||||
D0E3A7811B28ADD000A402D9 /* Postbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Postbox.swift; sourceTree = "<group>"; };
|
||||
D0E3A7831B28AE0900A402D9 /* Peer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Peer.swift; sourceTree = "<group>"; };
|
||||
D0E3A7871B28AE9C00A402D9 /* Coding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Coding.swift; sourceTree = "<group>"; };
|
||||
D0E3A79D1B28B50400A402D9 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
|
||||
D0E3A7A11B28B7DC00A402D9 /* Media.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Media.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -43,6 +96,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D07FC7D31B4A3D6B0010B3F7 /* SwiftSignalKit.framework in Frameworks */,
|
||||
D0E3A7561B28A7E300A402D9 /* Postbox.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -50,9 +104,56 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D07515FC1B2C44A200AE42E0 /* thirdparty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D07516731B2EC8C700AE42E0 /* sqlite.swift */,
|
||||
);
|
||||
name = thirdparty;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D075163D1B2D9CEF00AE42E0 /* PostboxPrivate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D075165D1B2EC5B500AE42E0 /* module.modulemap */,
|
||||
D075163F1B2D9CEF00AE42E0 /* sqlcipher */,
|
||||
);
|
||||
path = PostboxPrivate;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D075163F1B2D9CEF00AE42E0 /* sqlcipher */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D07516741B2EC90400AE42E0 /* fts3_tokenizer.h */,
|
||||
D07516751B2EC90400AE42E0 /* SQLite-Bridging.h */,
|
||||
D07516761B2EC90400AE42E0 /* SQLite-Bridging.m */,
|
||||
D07516401B2D9CEF00AE42E0 /* sqlite3.c */,
|
||||
D07516411B2D9CEF00AE42E0 /* sqlite3.h */,
|
||||
D07516421B2D9CEF00AE42E0 /* sqlite3ext.h */,
|
||||
);
|
||||
path = sqlcipher;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D07516731B2EC8C700AE42E0 /* sqlite.swift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D07516611B2EC7FE00AE42E0 /* Database.swift */,
|
||||
D07516621B2EC7FE00AE42E0 /* Expression.swift */,
|
||||
D07516631B2EC7FE00AE42E0 /* FTS.swift */,
|
||||
D07516651B2EC7FE00AE42E0 /* Functions.swift */,
|
||||
D07516661B2EC7FE00AE42E0 /* Query.swift */,
|
||||
D07516671B2EC7FE00AE42E0 /* Schema.swift */,
|
||||
D07516681B2EC7FE00AE42E0 /* Statement.swift */,
|
||||
D07516691B2EC7FE00AE42E0 /* Value.swift */,
|
||||
);
|
||||
name = sqlite.swift;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0E3A7401B28A7E300A402D9 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D07FC7D21B4A3D6B0010B3F7 /* SwiftSignalKit.framework */,
|
||||
D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */,
|
||||
D0E3A74C1B28A7E300A402D9 /* Postbox */,
|
||||
D0E3A7591B28A7E300A402D9 /* PostboxTests */,
|
||||
D0E3A74B1B28A7E300A402D9 /* Products */,
|
||||
@ -71,7 +172,15 @@
|
||||
D0E3A74C1B28A7E300A402D9 /* Postbox */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0E3A74F1B28A7E300A402D9 /* Postbox.h */,
|
||||
D075165B1B2EC5B000AE42E0 /* module.private.modulemap */,
|
||||
D075163D1B2D9CEF00AE42E0 /* PostboxPrivate */,
|
||||
D07515FC1B2C44A200AE42E0 /* thirdparty */,
|
||||
D0E3A7871B28AE9C00A402D9 /* Coding.swift */,
|
||||
D0E3A7831B28AE0900A402D9 /* Peer.swift */,
|
||||
D0E3A79D1B28B50400A402D9 /* Message.swift */,
|
||||
D0E3A7A11B28B7DC00A402D9 /* Media.swift */,
|
||||
D003E4E51B38DBDB00C22CBC /* MessageView.swift */,
|
||||
D0E3A7811B28ADD000A402D9 /* Postbox.swift */,
|
||||
D0E3A74D1B28A7E300A402D9 /* Supporting Files */,
|
||||
);
|
||||
path = Postbox;
|
||||
@ -80,6 +189,9 @@
|
||||
D0E3A74D1B28A7E300A402D9 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D044E1611B2AD667001EE087 /* MurMurHash32.h */,
|
||||
D044E1621B2AD677001EE087 /* MurMurHash32.m */,
|
||||
D0E3A74F1B28A7E300A402D9 /* Postbox.h */,
|
||||
D0E3A74E1B28A7E300A402D9 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
@ -90,6 +202,7 @@
|
||||
children = (
|
||||
D0E3A75C1B28A7E300A402D9 /* PostboxTests.swift */,
|
||||
D0E3A75A1B28A7E300A402D9 /* Supporting Files */,
|
||||
D044E15D1B2ACB9C001EE087 /* CodingTests.swift */,
|
||||
);
|
||||
path = PostboxTests;
|
||||
sourceTree = "<group>";
|
||||
@ -109,7 +222,12 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D07516771B2EC90400AE42E0 /* fts3_tokenizer.h in Headers */,
|
||||
D07516451B2D9CEF00AE42E0 /* sqlite3.h in Headers */,
|
||||
D07516781B2EC90400AE42E0 /* SQLite-Bridging.h in Headers */,
|
||||
D0E3A7501B28A7E300A402D9 /* Postbox.h in Headers */,
|
||||
D07516461B2D9CEF00AE42E0 /* sqlite3ext.h in Headers */,
|
||||
D044E1641B2AD718001EE087 /* MurMurHash32.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -158,6 +276,7 @@
|
||||
D0E3A7411B28A7E300A402D9 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = Telegram;
|
||||
TargetAttributes = {
|
||||
@ -209,6 +328,25 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D07516701B2EC7FE00AE42E0 /* Schema.swift in Sources */,
|
||||
D075165C1B2EC5B000AE42E0 /* module.private.modulemap in Sources */,
|
||||
D0E3A7821B28ADD000A402D9 /* Postbox.swift in Sources */,
|
||||
D0E3A79E1B28B50400A402D9 /* Message.swift in Sources */,
|
||||
D075166E1B2EC7FE00AE42E0 /* Functions.swift in Sources */,
|
||||
D044E1631B2AD677001EE087 /* MurMurHash32.m in Sources */,
|
||||
D07516721B2EC7FE00AE42E0 /* Value.swift in Sources */,
|
||||
D075166B1B2EC7FE00AE42E0 /* Expression.swift in Sources */,
|
||||
D0E3A7A21B28B7DC00A402D9 /* Media.swift in Sources */,
|
||||
D075166C1B2EC7FE00AE42E0 /* FTS.swift in Sources */,
|
||||
D0E3A7881B28AE9C00A402D9 /* Coding.swift in Sources */,
|
||||
D003E4E61B38DBDB00C22CBC /* MessageView.swift in Sources */,
|
||||
D075165E1B2EC5B500AE42E0 /* module.modulemap in Sources */,
|
||||
D07516791B2EC90400AE42E0 /* SQLite-Bridging.m in Sources */,
|
||||
D07516711B2EC7FE00AE42E0 /* Statement.swift in Sources */,
|
||||
D0E3A7841B28AE0900A402D9 /* Peer.swift in Sources */,
|
||||
D075166A1B2EC7FE00AE42E0 /* Database.swift in Sources */,
|
||||
D075166F1B2EC7FE00AE42E0 /* Query.swift in Sources */,
|
||||
D07516441B2D9CEF00AE42E0 /* sqlite3.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -216,6 +354,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D044E15E1B2ACB9C001EE087 /* CodingTests.swift in Sources */,
|
||||
D0E3A75D1B28A7E300A402D9 /* PostboxTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -233,6 +372,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D0E3A75E1B28A7E300A402D9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
@ -281,6 +421,7 @@
|
||||
};
|
||||
D0E3A75F1B28A7E300A402D9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
@ -322,29 +463,55 @@
|
||||
};
|
||||
D0E3A7611B28A7E300A402D9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/peter/Documents/PostBoxTest/submodules/SSignalKit/build/Debug-iphoneos",
|
||||
);
|
||||
INFOPLIST_FILE = Postbox/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_TEMP_STORE=2",
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS3",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D0E3A7621B28A7E300A402D9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/peter/Documents/PostBoxTest/submodules/SSignalKit/build/Debug-iphoneos",
|
||||
);
|
||||
INFOPLIST_FILE = Postbox/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_CFLAGS = (
|
||||
"-DSQLITE_TEMP_STORE=2",
|
||||
"-DSQLITE_HAS_CODEC=1",
|
||||
"-DSQLCIPHER_CRYPTO_CC=1",
|
||||
"-DSQLITE_ENABLE_FTS3",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
@ -352,10 +519,12 @@
|
||||
};
|
||||
D0E3A7641B28A7E300A402D9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D07516491B2D9E2500AE42E0 /* Postbox.xcconfig */;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"/Users/peter/Documents/PostBoxTest/submodules/SSignalKit/build/Debug-iphoneos",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@ -373,6 +542,7 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"/Users/peter/Documents/PostBoxTest/submodules/SSignalKit/build/Debug-iphoneos",
|
||||
);
|
||||
INFOPLIST_FILE = PostboxTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
@ -399,6 +569,7 @@
|
||||
D0E3A7621B28A7E300A402D9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D0E3A7631B28A7E300A402D9 /* Build configuration list for PBXNativeTarget "PostboxTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
@ -407,6 +578,7 @@
|
||||
D0E3A7651B28A7E300A402D9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
2
Postbox/Config/Postbox.xcconfig
Normal file
2
Postbox/Config/Postbox.xcconfig
Normal file
@ -0,0 +1,2 @@
|
||||
SWIFT_INCLUDE_PATHS = $(SRCROOT)/Postbox
|
||||
MODULEMAP_PRIVATE_FILE = $(SRCROOT)/Postbox/module.private.modulemap
|
365
Postbox/MessageView.swift
Normal file
365
Postbox/MessageView.swift
Normal file
@ -0,0 +1,365 @@
|
||||
import Foundation
|
||||
|
||||
public final class MutableMessageView: Printable {
|
||||
public struct RemoveContext {
|
||||
var invalidEarlier: Set<MessageId.Namespace>
|
||||
var invalidLater: Set<MessageId.Namespace>
|
||||
var removedMessages: Bool
|
||||
|
||||
init() {
|
||||
self.invalidEarlier = []
|
||||
self.invalidLater = []
|
||||
self.removedMessages = false
|
||||
}
|
||||
}
|
||||
|
||||
let namespaces: [MessageId.Namespace]
|
||||
let count: Int
|
||||
var earlier: [MessageId.Namespace : Message] = [:]
|
||||
var later: [MessageId.Namespace : Message] = [:]
|
||||
var messages: [Message]
|
||||
|
||||
public init(namespaces: [MessageId.Namespace], count: Int, earlier: [MessageId.Namespace : Message], messages: [Message], later: [MessageId.Namespace : Message]) {
|
||||
self.namespaces = namespaces
|
||||
self.count = count
|
||||
self.earlier = earlier
|
||||
self.later = later
|
||||
self.messages = messages
|
||||
}
|
||||
|
||||
public func add(message: Message) {
|
||||
if self.messages.count == 0 {
|
||||
self.messages.append(message)
|
||||
} else {
|
||||
var first = MessageIndex(self.messages[self.messages.count - 1])
|
||||
var last = MessageIndex(self.messages[0])
|
||||
|
||||
var next: MessageIndex?
|
||||
for namespace in self.namespaces {
|
||||
if let message = later[namespace] {
|
||||
let messageIndex = MessageIndex(message)
|
||||
if next == nil || messageIndex < next! {
|
||||
next = messageIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let index = MessageIndex(message)
|
||||
|
||||
if index < last {
|
||||
let earlierMessage = self.earlier[message.id.namespace]
|
||||
if earlierMessage == nil || earlierMessage!.id.id < message.id.id {
|
||||
if self.messages.count < self.count {
|
||||
self.messages.insert(message, atIndex: 0)
|
||||
} else {
|
||||
self.earlier[message.id.namespace] = message
|
||||
}
|
||||
}
|
||||
} else if index > first {
|
||||
if next != nil && index > next! {
|
||||
let laterMessage = self.later[message.id.namespace]
|
||||
if laterMessage == nil || laterMessage!.id.id > message.id.id {
|
||||
if self.messages.count < self.count {
|
||||
self.messages.append(message)
|
||||
} else {
|
||||
self.later[message.id.namespace] = message
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.messages.append(message)
|
||||
if self.messages.count > self.count {
|
||||
let earliest = self.messages[0]
|
||||
self.earlier[earliest.id.namespace] = earliest
|
||||
self.messages.removeAtIndex(0)
|
||||
}
|
||||
}
|
||||
} else if index != last && index != first {
|
||||
var i = self.messages.count
|
||||
while i >= 1 {
|
||||
if MessageIndex(self.messages[i - 1]) < index {
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
self.messages.insert(message, atIndex: i)
|
||||
if self.messages.count > self.count {
|
||||
let earliest = self.messages[0]
|
||||
self.earlier[earliest.id.namespace] = earliest
|
||||
self.messages.removeAtIndex(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func remove(ids: Set<MessageId>, context: RemoveContext? = nil) -> RemoveContext {
|
||||
var updatedContext = RemoveContext()
|
||||
if let context = context {
|
||||
updatedContext = context
|
||||
}
|
||||
|
||||
for (_, message) in self.earlier {
|
||||
if ids.contains(message.id) {
|
||||
updatedContext.invalidEarlier.insert(message.id.namespace)
|
||||
}
|
||||
}
|
||||
|
||||
for (_, message) in self.later {
|
||||
if ids.contains(message.id) {
|
||||
updatedContext.invalidLater.insert(message.id.namespace)
|
||||
}
|
||||
}
|
||||
|
||||
if self.messages.count != 0 {
|
||||
var i = self.messages.count - 1
|
||||
while i >= 0 {
|
||||
if ids.contains(self.messages[i].id) {
|
||||
self.messages.removeAtIndex(i)
|
||||
updatedContext.removedMessages = true
|
||||
}
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
return updatedContext
|
||||
}
|
||||
|
||||
public func complete(context: RemoveContext, fetchEarlier: (MessageId.Namespace, MessageId.Id?, Int) -> [Message], fetchLater: (MessageId.Namespace, MessageId.Id?, Int) -> [Message]) {
|
||||
if context.removedMessages {
|
||||
var addedMessages: [Message] = []
|
||||
|
||||
var latestAnchor: MessageIndex?
|
||||
if let lastMessage = self.messages.last {
|
||||
latestAnchor = MessageIndex(lastMessage)
|
||||
}
|
||||
|
||||
if latestAnchor == nil {
|
||||
var laterMessages: [Message] = []
|
||||
for (_, message) in self.later {
|
||||
let messageIndex = MessageIndex(message)
|
||||
if latestAnchor == nil || latestAnchor! > messageIndex {
|
||||
latestAnchor = messageIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for namespace in self.namespaces {
|
||||
if let later = self.later[namespace] {
|
||||
addedMessages += fetchLater(namespace, later.id.id - 1, self.count)
|
||||
}
|
||||
if let earlier = self.earlier[namespace] {
|
||||
addedMessages += fetchEarlier(namespace, earlier.id.id + 1, self.count)
|
||||
}
|
||||
}
|
||||
|
||||
addedMessages += self.messages
|
||||
addedMessages.sort({ MessageIndex($0) < MessageIndex($1) })
|
||||
var i = addedMessages.count - 1
|
||||
while i >= 1 {
|
||||
if addedMessages[i].id == addedMessages[i - 1].id {
|
||||
addedMessages.removeAtIndex(i)
|
||||
}
|
||||
i--
|
||||
}
|
||||
self.messages = []
|
||||
|
||||
var anchorIndex = addedMessages.count - 1
|
||||
if let latestAnchor = latestAnchor {
|
||||
var i = addedMessages.count - 1
|
||||
while i >= 0 {
|
||||
if MessageIndex(addedMessages[i]) <= latestAnchor {
|
||||
anchorIndex = i
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
self.later.removeAll(keepCapacity: true)
|
||||
|
||||
if anchorIndex + 1 < addedMessages.count {
|
||||
for namespace in self.namespaces {
|
||||
var i = anchorIndex + 1
|
||||
while i < addedMessages.count {
|
||||
if addedMessages[i].id.namespace == namespace {
|
||||
self.later[namespace] = addedMessages[i]
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = anchorIndex
|
||||
while i >= 0 && i > anchorIndex - self.count {
|
||||
self.messages.insert(addedMessages[i], atIndex: 0)
|
||||
i--
|
||||
}
|
||||
|
||||
self.earlier.removeAll(keepCapacity: true)
|
||||
if anchorIndex - self.count >= 0 {
|
||||
for namespace in self.namespaces {
|
||||
i = anchorIndex - self.count
|
||||
while i >= 0 {
|
||||
if addedMessages[i].id.namespace == namespace {
|
||||
self.earlier[namespace] = addedMessages[i]
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for namespace in context.invalidEarlier {
|
||||
var earlyId: MessageId.Id?
|
||||
var i = 0
|
||||
while i < self.messages.count {
|
||||
if self.messages[i].id.namespace == namespace {
|
||||
earlyId = self.messages[i].id.id
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
let earlierMessages = fetchEarlier(namespace, earlyId, 1)
|
||||
if earlierMessages.count == 0 {
|
||||
self.earlier.removeValueForKey(namespace)
|
||||
} else {
|
||||
self.earlier[namespace] = earlierMessages[0]
|
||||
}
|
||||
}
|
||||
|
||||
for namespace in context.invalidLater {
|
||||
var lateId: MessageId.Id?
|
||||
var i = self.messages.count - 1
|
||||
while i >= 0 {
|
||||
if self.messages[i].id.namespace == namespace {
|
||||
lateId = self.messages[i].id.id
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
let laterMessages = fetchLater(namespace, lateId, 1)
|
||||
if laterMessages.count == 0 {
|
||||
self.later.removeValueForKey(namespace)
|
||||
} else {
|
||||
self.later[namespace] = laterMessages[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
var string = ""
|
||||
string += "...("
|
||||
var first = true
|
||||
for namespace in self.namespaces {
|
||||
if let value = self.earlier[namespace] {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(namespace): \(value.id.id)—\(value.timestamp)"
|
||||
}
|
||||
}
|
||||
string += ") —— "
|
||||
|
||||
string += "["
|
||||
first = true
|
||||
for message in self.messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
|
||||
string += " —— ("
|
||||
first = true
|
||||
for namespace in self.namespaces {
|
||||
if let value = self.later[namespace] {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(namespace): \(value.id.id)—\(value.timestamp)"
|
||||
}
|
||||
}
|
||||
string += ")..."
|
||||
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
public final class MessageView: Printable {
|
||||
public let hasEarlier: Bool
|
||||
private let earlierIds: [MessageIndex]
|
||||
public let hasLater: Bool
|
||||
private let laterIds: [MessageIndex]
|
||||
public let messages: [Message]
|
||||
|
||||
init(_ mutableView: MutableMessageView) {
|
||||
self.hasEarlier = mutableView.earlier.count != 0
|
||||
self.hasLater = mutableView.later.count != 0
|
||||
self.messages = mutableView.messages
|
||||
|
||||
var earlierIds: [MessageIndex] = []
|
||||
for (_, message) in mutableView.earlier {
|
||||
earlierIds.append(MessageIndex(message))
|
||||
}
|
||||
self.earlierIds = earlierIds
|
||||
|
||||
var laterIds: [MessageIndex] = []
|
||||
for (_, message) in mutableView.later {
|
||||
laterIds.append(MessageIndex(message))
|
||||
}
|
||||
self.laterIds = laterIds
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
var string = ""
|
||||
if self.hasEarlier {
|
||||
string += "more("
|
||||
var first = true
|
||||
for id in self.earlierIds {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(id.id.namespace): \(id.id.id)—\(id.timestamp)"
|
||||
}
|
||||
string += ") "
|
||||
}
|
||||
string += "["
|
||||
var first = true
|
||||
for message in self.messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
if self.hasLater {
|
||||
string += " more("
|
||||
var first = true
|
||||
for id in self.laterIds {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(id.id.namespace): \(id.id.id)—\(id.timestamp)"
|
||||
}
|
||||
string += ")"
|
||||
}
|
||||
return string
|
||||
}
|
||||
}
|
9
Postbox/MurMurHash32.h
Normal file
9
Postbox/MurMurHash32.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef Postbox_MurMurHash32_h
|
||||
#define Postbox_MurMurHash32_h
|
||||
|
||||
#import <stdint.h>
|
||||
|
||||
int32_t murMurHash32(void *bytes, int length);
|
||||
int32_t murMurHashString32(const char *s);
|
||||
|
||||
#endif
|
98
Postbox/MurMurHash32.m
Normal file
98
Postbox/MurMurHash32.m
Normal file
@ -0,0 +1,98 @@
|
||||
#import "MurMurHash32.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FORCE_INLINE __attribute__((always_inline))
|
||||
|
||||
static inline uint32_t rotl32 ( uint32_t x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
||||
|
||||
static FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i )
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
static FORCE_INLINE uint32_t fmix ( uint32_t h )
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void murMurHash32Impl(const void *key, int len, uint32_t seed, void *out)
|
||||
{
|
||||
const uint8_t * data = (const uint8_t*)key;
|
||||
const int nblocks = len / 4;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
|
||||
|
||||
for(int i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = getblock(blocks,i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
|
||||
|
||||
uint32_t k1 = 0;
|
||||
|
||||
switch(len & 3)
|
||||
{
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h1 = fmix(h1);
|
||||
|
||||
*(uint32_t*)out = h1;
|
||||
}
|
||||
|
||||
int32_t murMurHash32(void *bytes, int length)
|
||||
{
|
||||
int32_t result = 0;
|
||||
murMurHash32Impl(bytes, length, -137723950, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t murMurHashString32(const char *s)
|
||||
{
|
||||
int32_t result = 0;
|
||||
murMurHash32Impl(s, (int)strlen(s), -137723950, &result);
|
||||
|
||||
return result;
|
||||
}
|
@ -16,4 +16,4 @@ FOUNDATION_EXPORT const unsigned char PostboxVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <Postbox/PublicHeader.h>
|
||||
|
||||
|
||||
#import <Postbox/MurMurHash32.h>
|
||||
|
7
Postbox/PostboxPrivate/module.modulemap
Normal file
7
Postbox/PostboxPrivate/module.modulemap
Normal file
@ -0,0 +1,7 @@
|
||||
module sqlcipher {
|
||||
header "sqlcipher/sqlite3.h"
|
||||
header "sqlcipher/sqlite3ext.h"
|
||||
header "sqlcipher/SQLite-Bridging.h"
|
||||
header "sqlcipher/fts3_tokenizer.h"
|
||||
export *
|
||||
}
|
56
Postbox/PostboxPrivate/sqlcipher/SQLite-Bridging.h
Normal file
56
Postbox/PostboxPrivate/sqlcipher/SQLite-Bridging.h
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// SQLite.swift
|
||||
// https://github.com/stephencelis/SQLite.swift
|
||||
// Copyright (c) 2014-2015 Stephen Celis.
|
||||
//
|
||||
// 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, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
typedef struct SQLiteHandle SQLiteHandle;
|
||||
typedef struct SQLiteContext SQLiteContext;
|
||||
typedef struct SQLiteValue SQLiteValue;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
typedef int (^_SQLiteBusyHandlerCallback)(int times);
|
||||
int _SQLiteBusyHandler(SQLiteHandle * handle, _SQLiteBusyHandlerCallback __nullable callback);
|
||||
|
||||
typedef void (^_SQLiteTraceCallback)(const char * SQL);
|
||||
void _SQLiteTrace(SQLiteHandle * handle, _SQLiteTraceCallback __nullable callback);
|
||||
|
||||
typedef void (^_SQLiteUpdateHookCallback)(int operation, const char * db, const char * table, long long rowid);
|
||||
void _SQLiteUpdateHook(SQLiteHandle * handle, _SQLiteUpdateHookCallback __nullable callback);
|
||||
|
||||
typedef int (^_SQLiteCommitHookCallback)();
|
||||
void _SQLiteCommitHook(SQLiteHandle * handle, _SQLiteCommitHookCallback __nullable callback);
|
||||
|
||||
typedef void (^_SQLiteRollbackHookCallback)();
|
||||
void _SQLiteRollbackHook(SQLiteHandle * handle, _SQLiteRollbackHookCallback __nullable callback);
|
||||
|
||||
typedef void (^_SQLiteCreateFunctionCallback)(SQLiteContext * context, int argc, SQLiteValue * __nonnull * __nonnull argv);
|
||||
int _SQLiteCreateFunction(SQLiteHandle * handle, const char * name, int argc, int deterministic, _SQLiteCreateFunctionCallback __nullable callback);
|
||||
|
||||
typedef int (^_SQLiteCreateCollationCallback)(const char * lhs, const char * rhs);
|
||||
int _SQLiteCreateCollation(SQLiteHandle * handle, const char * name, _SQLiteCreateCollationCallback __nullable callback);
|
||||
|
||||
typedef NSString * __nullable (^_SQLiteTokenizerNextCallback)(const char * input, int * inputOffset, int * inputLength);
|
||||
int _SQLiteRegisterTokenizer(SQLiteHandle * db, const char * module, const char * tokenizer, __nullable _SQLiteTokenizerNextCallback callback);
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
217
Postbox/PostboxPrivate/sqlcipher/SQLite-Bridging.m
Normal file
217
Postbox/PostboxPrivate/sqlcipher/SQLite-Bridging.m
Normal file
@ -0,0 +1,217 @@
|
||||
//
|
||||
// SQLite.swift
|
||||
// https://github.com/stephencelis/SQLite.swift
|
||||
// Copyright (c) 2014-2015 Stephen Celis.
|
||||
//
|
||||
// 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, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#import "SQLite-Bridging.h"
|
||||
|
||||
#import "fts3_tokenizer.h"
|
||||
|
||||
static int __SQLiteBusyHandler(void * context, int tries) {
|
||||
return ((__bridge _SQLiteBusyHandlerCallback)context)(tries);
|
||||
}
|
||||
|
||||
int _SQLiteBusyHandler(SQLiteHandle * handle, _SQLiteBusyHandlerCallback callback) {
|
||||
if (callback) {
|
||||
return sqlite3_busy_handler((sqlite3 *)handle, __SQLiteBusyHandler, (__bridge void *)callback);
|
||||
} else {
|
||||
return sqlite3_busy_handler((sqlite3 *)handle, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void __SQLiteTrace(void * context, const char * SQL) {
|
||||
((__bridge _SQLiteTraceCallback)context)(SQL);
|
||||
}
|
||||
|
||||
void _SQLiteTrace(SQLiteHandle * handle, _SQLiteTraceCallback callback) {
|
||||
if (callback) {
|
||||
sqlite3_trace((sqlite3 *)handle, __SQLiteTrace, (__bridge void *)callback);
|
||||
} else {
|
||||
sqlite3_trace((sqlite3 *)handle, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void __SQLiteUpdateHook(void * context, int operation, const char * db, const char * table, long long rowid) {
|
||||
((__bridge _SQLiteUpdateHookCallback)context)(operation, db, table, rowid);
|
||||
}
|
||||
|
||||
void _SQLiteUpdateHook(SQLiteHandle * handle, _SQLiteUpdateHookCallback callback) {
|
||||
sqlite3_update_hook((sqlite3 *)handle, __SQLiteUpdateHook, (__bridge void *)callback);
|
||||
}
|
||||
|
||||
static int __SQLiteCommitHook(void * context) {
|
||||
return ((__bridge _SQLiteCommitHookCallback)context)();
|
||||
}
|
||||
|
||||
void _SQLiteCommitHook(SQLiteHandle * handle, _SQLiteCommitHookCallback callback) {
|
||||
sqlite3_commit_hook((sqlite3 *)handle, __SQLiteCommitHook, (__bridge void *)callback);
|
||||
}
|
||||
|
||||
static void __SQLiteRollbackHook(void * context) {
|
||||
((__bridge _SQLiteRollbackHookCallback)context)();
|
||||
}
|
||||
|
||||
void _SQLiteRollbackHook(SQLiteHandle * handle, _SQLiteRollbackHookCallback callback) {
|
||||
sqlite3_rollback_hook((sqlite3 *)handle, __SQLiteRollbackHook, (__bridge void *)callback);
|
||||
}
|
||||
|
||||
static void __SQLiteCreateFunction(sqlite3_context * context, int argc, sqlite3_value ** argv) {
|
||||
((__bridge _SQLiteCreateFunctionCallback)sqlite3_user_data(context))((SQLiteContext *)context, argc, (SQLiteValue **)argv);
|
||||
}
|
||||
|
||||
int _SQLiteCreateFunction(SQLiteHandle * handle, const char * name, int argc, int deterministic, _SQLiteCreateFunctionCallback callback) {
|
||||
if (callback) {
|
||||
int flags = SQLITE_UTF8;
|
||||
if (deterministic) {
|
||||
#ifdef SQLITE_DETERMINISTIC
|
||||
flags |= SQLITE_DETERMINISTIC;
|
||||
#endif
|
||||
}
|
||||
return sqlite3_create_function_v2((sqlite3 *)handle, name, -1, flags, (__bridge void *)callback, &__SQLiteCreateFunction, 0, 0, 0);
|
||||
} else {
|
||||
return sqlite3_create_function_v2((sqlite3 *)handle, name, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int __SQLiteCreateCollation(void * context, int len_lhs, const void * lhs, int len_rhs, const void * rhs) {
|
||||
return ((__bridge _SQLiteCreateCollationCallback)context)(lhs, rhs);
|
||||
}
|
||||
|
||||
int _SQLiteCreateCollation(SQLiteHandle * handle, const char * name, _SQLiteCreateCollationCallback callback) {
|
||||
if (callback) {
|
||||
return sqlite3_create_collation_v2((sqlite3 *)handle, name, SQLITE_UTF8, (__bridge void *)callback, &__SQLiteCreateCollation, 0);
|
||||
} else {
|
||||
return sqlite3_create_collation_v2((sqlite3 *)handle, name, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FTS
|
||||
|
||||
typedef struct __SQLiteTokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
__unsafe_unretained _SQLiteTokenizerNextCallback callback;
|
||||
} __SQLiteTokenizer;
|
||||
|
||||
typedef struct __SQLiteTokenizerCursor {
|
||||
void * base;
|
||||
const char * input;
|
||||
int inputOffset;
|
||||
int inputLength;
|
||||
int idx;
|
||||
} __SQLiteTokenizerCursor;
|
||||
|
||||
static NSMutableDictionary * __SQLiteTokenizerMap;
|
||||
|
||||
static int __SQLiteTokenizerCreate(int argc, const char * const * argv, sqlite3_tokenizer ** ppTokenizer) {
|
||||
__SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)sqlite3_malloc(sizeof(__SQLiteTokenizer));
|
||||
if (!tokenizer) {
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(tokenizer, 0, sizeof(* tokenizer)); // FIXME: needed?
|
||||
|
||||
NSString * key = [NSString stringWithUTF8String:argv[0]];
|
||||
tokenizer->callback = [__SQLiteTokenizerMap objectForKey:key];
|
||||
if (!tokenizer->callback) {
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
*ppTokenizer = &tokenizer->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int __SQLiteTokenizerDestroy(sqlite3_tokenizer * pTokenizer) {
|
||||
sqlite3_free(pTokenizer);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int __SQLiteTokenizerOpen(sqlite3_tokenizer * pTokenizer, const char * pInput, int nBytes, sqlite3_tokenizer_cursor ** ppCursor) {
|
||||
__SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)sqlite3_malloc(sizeof(__SQLiteTokenizerCursor));
|
||||
if (!cursor) {
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
cursor->input = pInput;
|
||||
cursor->inputOffset = 0;
|
||||
cursor->inputLength = 0;
|
||||
cursor->idx = 0;
|
||||
|
||||
*ppCursor = (sqlite3_tokenizer_cursor *)cursor;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int __SQLiteTokenizerClose(sqlite3_tokenizer_cursor * pCursor) {
|
||||
sqlite3_free(pCursor);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int __SQLiteTokenizerNext(sqlite3_tokenizer_cursor * pCursor, const char ** ppToken, int * pnBytes, int * piStartOffset, int * piEndOffset, int * piPosition) {
|
||||
__SQLiteTokenizerCursor * cursor = (__SQLiteTokenizerCursor *)pCursor;
|
||||
__SQLiteTokenizer * tokenizer = (__SQLiteTokenizer *)cursor->base;
|
||||
|
||||
cursor->inputOffset += cursor->inputLength;
|
||||
const char * input = cursor->input + cursor->inputOffset;
|
||||
const char * token = [tokenizer->callback(input, &cursor->inputOffset, &cursor->inputLength) cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
if (!token) {
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
|
||||
*ppToken = token;
|
||||
*pnBytes = (int)strlen(token);
|
||||
*piStartOffset = cursor->inputOffset;
|
||||
*piEndOffset = cursor->inputOffset + cursor->inputLength;
|
||||
*piPosition = cursor->idx++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static const sqlite3_tokenizer_module __SQLiteTokenizerModule = {
|
||||
0,
|
||||
__SQLiteTokenizerCreate,
|
||||
__SQLiteTokenizerDestroy,
|
||||
__SQLiteTokenizerOpen,
|
||||
__SQLiteTokenizerClose,
|
||||
__SQLiteTokenizerNext
|
||||
};
|
||||
|
||||
int _SQLiteRegisterTokenizer(SQLiteHandle * db, const char * moduleName, const char * submoduleName, _SQLiteTokenizerNextCallback callback) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
__SQLiteTokenizerMap = [NSMutableDictionary new];
|
||||
});
|
||||
|
||||
sqlite3_stmt * stmt;
|
||||
int status = sqlite3_prepare_v2((sqlite3 *)db, "SELECT fts3_tokenizer(?, ?)", -1, &stmt, 0);
|
||||
if (status != SQLITE_OK ){
|
||||
return status;
|
||||
}
|
||||
const sqlite3_tokenizer_module * pModule = &__SQLiteTokenizerModule;
|
||||
sqlite3_bind_text(stmt, 1, moduleName, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_blob(stmt, 2, &pModule, sizeof(pModule), SQLITE_STATIC);
|
||||
sqlite3_step(stmt);
|
||||
status = sqlite3_finalize(stmt);
|
||||
if (status != SQLITE_OK ){
|
||||
return status;
|
||||
}
|
||||
|
||||
[__SQLiteTokenizerMap setObject:[callback copy] forKey:[NSString stringWithUTF8String:submoduleName]];
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
161
Postbox/PostboxPrivate/sqlcipher/fts3_tokenizer.h
Normal file
161
Postbox/PostboxPrivate/sqlcipher/fts3_tokenizer.h
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
** 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 <tokenizer-name> 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_ */
|
151821
Postbox/PostboxPrivate/sqlcipher/sqlite3.c
Normal file
151821
Postbox/PostboxPrivate/sqlcipher/sqlite3.c
Normal file
File diff suppressed because it is too large
Load Diff
7494
Postbox/PostboxPrivate/sqlcipher/sqlite3.h
Normal file
7494
Postbox/PostboxPrivate/sqlcipher/sqlite3.h
Normal file
File diff suppressed because it is too large
Load Diff
487
Postbox/PostboxPrivate/sqlcipher/sqlite3ext.h
Normal file
487
Postbox/PostboxPrivate/sqlcipher/sqlite3ext.h
Normal file
@ -0,0 +1,487 @@
|
||||
/*
|
||||
** 2006 June 7
|
||||
**
|
||||
** 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 defines the SQLite interface for use by
|
||||
** shared libraries that want to be imported as extensions into
|
||||
** an SQLite instance. Shared libraries that intend to be loaded
|
||||
** as extensions by SQLite should #include this file instead of
|
||||
** sqlite3.h.
|
||||
*/
|
||||
#ifndef _SQLITE3EXT_H_
|
||||
#define _SQLITE3EXT_H_
|
||||
#include "sqlite3.h"
|
||||
|
||||
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
|
||||
/*
|
||||
** The following structure holds pointers to all of the SQLite API
|
||||
** routines.
|
||||
**
|
||||
** WARNING: In order to maintain backwards compatibility, add new
|
||||
** interfaces to the end of this structure only. If you insert new
|
||||
** interfaces in the middle of this structure, then older different
|
||||
** versions of SQLite will not be able to load each others' shared
|
||||
** libraries!
|
||||
*/
|
||||
struct sqlite3_api_routines {
|
||||
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
||||
int (*aggregate_count)(sqlite3_context*);
|
||||
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
||||
int (*bind_double)(sqlite3_stmt*,int,double);
|
||||
int (*bind_int)(sqlite3_stmt*,int,int);
|
||||
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
||||
int (*bind_null)(sqlite3_stmt*,int);
|
||||
int (*bind_parameter_count)(sqlite3_stmt*);
|
||||
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
||||
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
||||
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
||||
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
||||
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
||||
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
||||
int (*busy_timeout)(sqlite3*,int ms);
|
||||
int (*changes)(sqlite3*);
|
||||
int (*close)(sqlite3*);
|
||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const char*));
|
||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
||||
int eTextRep,const void*));
|
||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_count)(sqlite3_stmt*pStmt);
|
||||
const char * (*column_database_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
||||
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
||||
double (*column_double)(sqlite3_stmt*,int iCol);
|
||||
int (*column_int)(sqlite3_stmt*,int iCol);
|
||||
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
||||
const char * (*column_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
||||
const char * (*column_table_name)(sqlite3_stmt*,int);
|
||||
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
||||
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
||||
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
||||
int (*column_type)(sqlite3_stmt*,int iCol);
|
||||
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
||||
int (*complete)(const char*sql);
|
||||
int (*complete16)(const void*sql);
|
||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*));
|
||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*));
|
||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
||||
int (*data_count)(sqlite3_stmt*pStmt);
|
||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
||||
int (*declare_vtab)(sqlite3*,const char*);
|
||||
int (*enable_shared_cache)(int);
|
||||
int (*errcode)(sqlite3*db);
|
||||
const char * (*errmsg)(sqlite3*);
|
||||
const void * (*errmsg16)(sqlite3*);
|
||||
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
||||
int (*expired)(sqlite3_stmt*);
|
||||
int (*finalize)(sqlite3_stmt*pStmt);
|
||||
void (*free)(void*);
|
||||
void (*free_table)(char**result);
|
||||
int (*get_autocommit)(sqlite3*);
|
||||
void * (*get_auxdata)(sqlite3_context*,int);
|
||||
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
||||
int (*global_recover)(void);
|
||||
void (*interruptx)(sqlite3*);
|
||||
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
||||
const char * (*libversion)(void);
|
||||
int (*libversion_number)(void);
|
||||
void *(*malloc)(int);
|
||||
char * (*mprintf)(const char*,...);
|
||||
int (*open)(const char*,sqlite3**);
|
||||
int (*open16)(const void*,sqlite3**);
|
||||
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
||||
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
||||
void *(*realloc)(void*,int);
|
||||
int (*reset)(sqlite3_stmt*pStmt);
|
||||
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_double)(sqlite3_context*,double);
|
||||
void (*result_error)(sqlite3_context*,const char*,int);
|
||||
void (*result_error16)(sqlite3_context*,const void*,int);
|
||||
void (*result_int)(sqlite3_context*,int);
|
||||
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
||||
void (*result_null)(sqlite3_context*);
|
||||
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
||||
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||
const char*,const char*),void*);
|
||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||
char * (*snprintf)(int,char*,const char*,...);
|
||||
int (*step)(sqlite3_stmt*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||
char const**,char const**,int*,int*,int*);
|
||||
void (*thread_cleanup)(void);
|
||||
int (*total_changes)(sqlite3*);
|
||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
||||
sqlite_int64),void*);
|
||||
void * (*user_data)(sqlite3_context*);
|
||||
const void * (*value_blob)(sqlite3_value*);
|
||||
int (*value_bytes)(sqlite3_value*);
|
||||
int (*value_bytes16)(sqlite3_value*);
|
||||
double (*value_double)(sqlite3_value*);
|
||||
int (*value_int)(sqlite3_value*);
|
||||
sqlite_int64 (*value_int64)(sqlite3_value*);
|
||||
int (*value_numeric_type)(sqlite3_value*);
|
||||
const unsigned char * (*value_text)(sqlite3_value*);
|
||||
const void * (*value_text16)(sqlite3_value*);
|
||||
const void * (*value_text16be)(sqlite3_value*);
|
||||
const void * (*value_text16le)(sqlite3_value*);
|
||||
int (*value_type)(sqlite3_value*);
|
||||
char *(*vmprintf)(const char*,va_list);
|
||||
/* Added ??? */
|
||||
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
||||
/* Added by 3.3.13 */
|
||||
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
||||
int (*clear_bindings)(sqlite3_stmt*);
|
||||
/* Added by 3.4.1 */
|
||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
||||
void (*xDestroy)(void *));
|
||||
/* Added by 3.5.0 */
|
||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
||||
int (*blob_bytes)(sqlite3_blob*);
|
||||
int (*blob_close)(sqlite3_blob*);
|
||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
||||
int,sqlite3_blob**);
|
||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
||||
int(*)(void*,int,const void*,int,const void*),
|
||||
void(*)(void*));
|
||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
||||
sqlite3_int64 (*memory_highwater)(int);
|
||||
sqlite3_int64 (*memory_used)(void);
|
||||
sqlite3_mutex *(*mutex_alloc)(int);
|
||||
void (*mutex_enter)(sqlite3_mutex*);
|
||||
void (*mutex_free)(sqlite3_mutex*);
|
||||
void (*mutex_leave)(sqlite3_mutex*);
|
||||
int (*mutex_try)(sqlite3_mutex*);
|
||||
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
||||
int (*release_memory)(int);
|
||||
void (*result_error_nomem)(sqlite3_context*);
|
||||
void (*result_error_toobig)(sqlite3_context*);
|
||||
int (*sleep)(int);
|
||||
void (*soft_heap_limit)(int);
|
||||
sqlite3_vfs *(*vfs_find)(const char*);
|
||||
int (*vfs_register)(sqlite3_vfs*,int);
|
||||
int (*vfs_unregister)(sqlite3_vfs*);
|
||||
int (*xthreadsafe)(void);
|
||||
void (*result_zeroblob)(sqlite3_context*,int);
|
||||
void (*result_error_code)(sqlite3_context*,int);
|
||||
int (*test_control)(int, ...);
|
||||
void (*randomness)(int,void*);
|
||||
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
||||
int (*extended_result_codes)(sqlite3*,int);
|
||||
int (*limit)(sqlite3*,int,int);
|
||||
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
||||
const char *(*sql)(sqlite3_stmt*);
|
||||
int (*status)(int,int*,int*,int);
|
||||
int (*backup_finish)(sqlite3_backup*);
|
||||
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
||||
int (*backup_pagecount)(sqlite3_backup*);
|
||||
int (*backup_remaining)(sqlite3_backup*);
|
||||
int (*backup_step)(sqlite3_backup*,int);
|
||||
const char *(*compileoption_get)(int);
|
||||
int (*compileoption_used)(const char*);
|
||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||
void (*xFinal)(sqlite3_context*),
|
||||
void(*xDestroy)(void*));
|
||||
int (*db_config)(sqlite3*,int,...);
|
||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
||||
int (*extended_errcode)(sqlite3*);
|
||||
void (*log)(int,const char*,...);
|
||||
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
||||
const char *(*sourceid)(void);
|
||||
int (*stmt_status)(sqlite3_stmt*,int,int);
|
||||
int (*strnicmp)(const char*,const char*,int);
|
||||
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||
int (*vtab_config)(sqlite3*,int op,...);
|
||||
int (*vtab_on_conflict)(sqlite3*);
|
||||
/* Version 3.7.16 and later */
|
||||
int (*close_v2)(sqlite3*);
|
||||
const char *(*db_filename)(sqlite3*,const char*);
|
||||
int (*db_readonly)(sqlite3*,const char*);
|
||||
int (*db_release_memory)(sqlite3*);
|
||||
const char *(*errstr)(int);
|
||||
int (*stmt_busy)(sqlite3_stmt*);
|
||||
int (*stmt_readonly)(sqlite3_stmt*);
|
||||
int (*stricmp)(const char*,const char*);
|
||||
int (*uri_boolean)(const char*,const char*,int);
|
||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
};
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected throught the global sqlite3_api structure.
|
||||
**
|
||||
** This header file is also used by the loadext.c source file
|
||||
** (part of the main SQLite library - not an extension) so that
|
||||
** it can get access to the sqlite3_api_routines structure
|
||||
** definition. But the main library does not want to redefine
|
||||
** the API. So the redefinition macros are only valid if the
|
||||
** SQLITE_CORE macros is undefined.
|
||||
*/
|
||||
#ifndef SQLITE_CORE
|
||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||
#endif
|
||||
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
||||
#define sqlite3_bind_double sqlite3_api->bind_double
|
||||
#define sqlite3_bind_int sqlite3_api->bind_int
|
||||
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
||||
#define sqlite3_bind_null sqlite3_api->bind_null
|
||||
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
||||
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
||||
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
||||
#define sqlite3_bind_text sqlite3_api->bind_text
|
||||
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
||||
#define sqlite3_bind_value sqlite3_api->bind_value
|
||||
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
||||
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
||||
#define sqlite3_changes sqlite3_api->changes
|
||||
#define sqlite3_close sqlite3_api->close
|
||||
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
||||
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
||||
#define sqlite3_column_blob sqlite3_api->column_blob
|
||||
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
||||
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
||||
#define sqlite3_column_count sqlite3_api->column_count
|
||||
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
||||
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
||||
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
||||
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
||||
#define sqlite3_column_double sqlite3_api->column_double
|
||||
#define sqlite3_column_int sqlite3_api->column_int
|
||||
#define sqlite3_column_int64 sqlite3_api->column_int64
|
||||
#define sqlite3_column_name sqlite3_api->column_name
|
||||
#define sqlite3_column_name16 sqlite3_api->column_name16
|
||||
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
||||
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
||||
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
||||
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
||||
#define sqlite3_column_text sqlite3_api->column_text
|
||||
#define sqlite3_column_text16 sqlite3_api->column_text16
|
||||
#define sqlite3_column_type sqlite3_api->column_type
|
||||
#define sqlite3_column_value sqlite3_api->column_value
|
||||
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
||||
#define sqlite3_complete sqlite3_api->complete
|
||||
#define sqlite3_complete16 sqlite3_api->complete16
|
||||
#define sqlite3_create_collation sqlite3_api->create_collation
|
||||
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
||||
#define sqlite3_create_function sqlite3_api->create_function
|
||||
#define sqlite3_create_function16 sqlite3_api->create_function16
|
||||
#define sqlite3_create_module sqlite3_api->create_module
|
||||
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
||||
#define sqlite3_data_count sqlite3_api->data_count
|
||||
#define sqlite3_db_handle sqlite3_api->db_handle
|
||||
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
||||
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
||||
#define sqlite3_errcode sqlite3_api->errcode
|
||||
#define sqlite3_errmsg sqlite3_api->errmsg
|
||||
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
||||
#define sqlite3_exec sqlite3_api->exec
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_expired sqlite3_api->expired
|
||||
#endif
|
||||
#define sqlite3_finalize sqlite3_api->finalize
|
||||
#define sqlite3_free sqlite3_api->free
|
||||
#define sqlite3_free_table sqlite3_api->free_table
|
||||
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
||||
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
||||
#define sqlite3_get_table sqlite3_api->get_table
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_global_recover sqlite3_api->global_recover
|
||||
#endif
|
||||
#define sqlite3_interrupt sqlite3_api->interruptx
|
||||
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
||||
#define sqlite3_libversion sqlite3_api->libversion
|
||||
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
||||
#define sqlite3_malloc sqlite3_api->malloc
|
||||
#define sqlite3_mprintf sqlite3_api->mprintf
|
||||
#define sqlite3_open sqlite3_api->open
|
||||
#define sqlite3_open16 sqlite3_api->open16
|
||||
#define sqlite3_prepare sqlite3_api->prepare
|
||||
#define sqlite3_prepare16 sqlite3_api->prepare16
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_profile sqlite3_api->profile
|
||||
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
||||
#define sqlite3_realloc sqlite3_api->realloc
|
||||
#define sqlite3_reset sqlite3_api->reset
|
||||
#define sqlite3_result_blob sqlite3_api->result_blob
|
||||
#define sqlite3_result_double sqlite3_api->result_double
|
||||
#define sqlite3_result_error sqlite3_api->result_error
|
||||
#define sqlite3_result_error16 sqlite3_api->result_error16
|
||||
#define sqlite3_result_int sqlite3_api->result_int
|
||||
#define sqlite3_result_int64 sqlite3_api->result_int64
|
||||
#define sqlite3_result_null sqlite3_api->result_null
|
||||
#define sqlite3_result_text sqlite3_api->result_text
|
||||
#define sqlite3_result_text16 sqlite3_api->result_text16
|
||||
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
||||
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
||||
#define sqlite3_result_value sqlite3_api->result_value
|
||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||
#define sqlite3_snprintf sqlite3_api->snprintf
|
||||
#define sqlite3_step sqlite3_api->step
|
||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||
#define sqlite3_total_changes sqlite3_api->total_changes
|
||||
#define sqlite3_trace sqlite3_api->trace
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
||||
#endif
|
||||
#define sqlite3_update_hook sqlite3_api->update_hook
|
||||
#define sqlite3_user_data sqlite3_api->user_data
|
||||
#define sqlite3_value_blob sqlite3_api->value_blob
|
||||
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
||||
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
||||
#define sqlite3_value_double sqlite3_api->value_double
|
||||
#define sqlite3_value_int sqlite3_api->value_int
|
||||
#define sqlite3_value_int64 sqlite3_api->value_int64
|
||||
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
||||
#define sqlite3_value_text sqlite3_api->value_text
|
||||
#define sqlite3_value_text16 sqlite3_api->value_text16
|
||||
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||
#define sqlite3_value_type sqlite3_api->value_type
|
||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
||||
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
||||
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
||||
#define sqlite3_blob_close sqlite3_api->blob_close
|
||||
#define sqlite3_blob_open sqlite3_api->blob_open
|
||||
#define sqlite3_blob_read sqlite3_api->blob_read
|
||||
#define sqlite3_blob_write sqlite3_api->blob_write
|
||||
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
||||
#define sqlite3_file_control sqlite3_api->file_control
|
||||
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
||||
#define sqlite3_memory_used sqlite3_api->memory_used
|
||||
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
||||
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
||||
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
||||
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
||||
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
||||
#define sqlite3_open_v2 sqlite3_api->open_v2
|
||||
#define sqlite3_release_memory sqlite3_api->release_memory
|
||||
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
||||
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
||||
#define sqlite3_sleep sqlite3_api->sleep
|
||||
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
||||
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
||||
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
||||
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
||||
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
||||
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
||||
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
||||
#define sqlite3_test_control sqlite3_api->test_control
|
||||
#define sqlite3_randomness sqlite3_api->randomness
|
||||
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
||||
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
||||
#define sqlite3_limit sqlite3_api->limit
|
||||
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
||||
#define sqlite3_sql sqlite3_api->sql
|
||||
#define sqlite3_status sqlite3_api->status
|
||||
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
||||
#define sqlite3_backup_init sqlite3_api->backup_init
|
||||
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
||||
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
||||
#define sqlite3_backup_step sqlite3_api->backup_step
|
||||
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
||||
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
||||
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
||||
#define sqlite3_db_config sqlite3_api->db_config
|
||||
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
||||
#define sqlite3_db_status sqlite3_api->db_status
|
||||
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
||||
#define sqlite3_log sqlite3_api->log
|
||||
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
||||
#define sqlite3_sourceid sqlite3_api->sourceid
|
||||
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
||||
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
||||
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||
/* Version 3.7.16 and later */
|
||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
||||
#define sqlite3_errstr sqlite3_api->errstr
|
||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
#endif /* SQLITE_CORE */
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
/* This case when the file really is being compiled as a loadable
|
||||
** extension */
|
||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
||||
# define SQLITE_EXTENSION_INIT3 \
|
||||
extern const sqlite3_api_routines *sqlite3_api;
|
||||
#else
|
||||
/* This case when the file is being statically linked into the
|
||||
** application */
|
||||
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
||||
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITE3EXT_H_ */
|
3
Postbox/module.private.modulemap
Normal file
3
Postbox/module.private.modulemap
Normal file
@ -0,0 +1,3 @@
|
||||
module PostboxPrivate {
|
||||
export *
|
||||
}
|
159
PostboxTests/CodingTests.swift
Normal file
159
PostboxTests/CodingTests.swift
Normal file
@ -0,0 +1,159 @@
|
||||
import UIKit
|
||||
import XCTest
|
||||
|
||||
import Postbox
|
||||
|
||||
class TestParent: Coding, Equatable {
|
||||
var parentInt32: Int32
|
||||
|
||||
required init(decoder: Decoder) {
|
||||
self.parentInt32 = decoder.decodeInt32ForKey("parentInt32")
|
||||
}
|
||||
|
||||
init(parentInt32: Int32) {
|
||||
self.parentInt32 = parentInt32
|
||||
}
|
||||
|
||||
func encode(encoder: Encoder) {
|
||||
encoder.encodeInt32(self.parentInt32, forKey: "parentInt32")
|
||||
}
|
||||
}
|
||||
|
||||
class TestObject: TestParent {
|
||||
var int32: Int32
|
||||
var int64: Int64
|
||||
var double: Double
|
||||
var string: String
|
||||
var int32Array: [Int32]
|
||||
var int64Array: [Int64]
|
||||
|
||||
required init(decoder: Decoder) {
|
||||
self.int32 = decoder.decodeInt32ForKey("int32")
|
||||
self.int64 = decoder.decodeInt64ForKey("int64")
|
||||
self.double = decoder.decodeDoubleForKey("double")
|
||||
self.string = decoder.decodeStringForKey("string")
|
||||
self.int32Array = decoder.decodeInt32ArrayForKey("int32Array")
|
||||
self.int64Array = decoder.decodeInt64ArrayForKey("int64Array")
|
||||
super.init(decoder: decoder)
|
||||
}
|
||||
|
||||
init(parentInt32: Int32, int32: Int32, int64: Int64, double: Double, string: String, int32Array: [Int32], int64Array: [Int64]) {
|
||||
self.int32 = int32
|
||||
self.int64 = int64
|
||||
self.double = double
|
||||
self.string = string
|
||||
self.int32Array = int32Array
|
||||
self.int64Array = int64Array
|
||||
super.init(parentInt32: parentInt32)
|
||||
}
|
||||
|
||||
override func encode(encoder: Encoder) {
|
||||
encoder.encodeInt32(self.int32, forKey: "int32")
|
||||
encoder.encodeInt64(self.int64, forKey: "int64")
|
||||
encoder.encodeDouble(self.double, forKey: "double")
|
||||
encoder.encodeString(self.string, forKey: "string")
|
||||
encoder.encodeInt32Array(self.int32Array, forKey: "int32Array")
|
||||
encoder.encodeInt64Array(self.int64Array, forKey: "int64Array")
|
||||
super.encode(encoder)
|
||||
}
|
||||
}
|
||||
|
||||
class TestKey: Coding, Hashable {
|
||||
let value: Int
|
||||
required init(decoder: Decoder) {
|
||||
self.value = Int(decoder.decodeInt32ForKey("value"))
|
||||
}
|
||||
|
||||
init(value: Int) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
func encode(encoder: Encoder) {
|
||||
encoder.encodeInt32(Int32(self.value), forKey: "value")
|
||||
}
|
||||
|
||||
var hashValue: Int {
|
||||
get {
|
||||
return self.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ==(lhs: TestObject, rhs: TestObject) -> Bool {
|
||||
return lhs.int32 == rhs.int32 &&
|
||||
lhs.int64 == rhs.int64 &&
|
||||
lhs.double == rhs.double &&
|
||||
lhs.string == rhs.string &&
|
||||
lhs.int32Array == rhs.int32Array &&
|
||||
lhs.int64Array == rhs.int64Array &&
|
||||
lhs.parentInt32 == rhs.parentInt32
|
||||
}
|
||||
|
||||
func ==(lhs: TestParent, rhs: TestParent) -> Bool {
|
||||
return lhs.parentInt32 == rhs.parentInt32
|
||||
}
|
||||
|
||||
func ==(lhs: TestKey, rhs: TestKey) -> Bool {
|
||||
return lhs.value == rhs.value
|
||||
}
|
||||
|
||||
class SerializationTests: XCTestCase {
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
declareEncodable(TestParent.self, { TestParent(decoder: $0) })
|
||||
declareEncodable(TestObject.self, { TestObject(decoder: $0) })
|
||||
declareEncodable(TestKey.self, { TestKey(decoder: $0) })
|
||||
|
||||
let encoder = Encoder()
|
||||
encoder.encodeInt32(12345, forKey: "a")
|
||||
encoder.encodeInt64(Int64(12345), forKey: "b")
|
||||
encoder.encodeBool(true, forKey: "c")
|
||||
encoder.encodeString("test", forKey: "d")
|
||||
|
||||
let before = TestObject(parentInt32: 100, int32: 12345, int64: 67890, double: 1.23456, string: "test", int32Array: [1, 2, 3, 4, 5], int64Array: [6, 7, 8, 9, 0])
|
||||
encoder.encodeObject(before, forKey: "e")
|
||||
|
||||
encoder.encodeInt32Array([1, 2, 3, 4], forKey: "f")
|
||||
encoder.encodeInt64Array([1, 2, 3, 4], forKey: "g")
|
||||
|
||||
let beforeArray: [TestParent] = [TestObject(parentInt32: 1000, int32: 12345, int64: 67890, double: 1.23456, string: "test", int32Array: [1, 2, 3, 4, 5], int64Array: [6, 7, 8, 9, 0]), TestParent(parentInt32: 2000)]
|
||||
|
||||
encoder.encodeObjectArray(beforeArray, forKey: "h")
|
||||
|
||||
let beforeDictionary: [TestKey : TestParent] = [
|
||||
TestKey(value: 1): TestObject(parentInt32: 1000, int32: 12345, int64: 67890, double: 1.23456, string: "test", int32Array: [1, 2, 3, 4, 5], int64Array: [6, 7, 8, 9, 0]),
|
||||
TestKey(value: 2): TestParent(parentInt32: 2000)
|
||||
]
|
||||
|
||||
encoder.encodeObjectDictionary(beforeDictionary, forKey: "i")
|
||||
|
||||
let decoder = Decoder(buffer: encoder.makeReadBufferAndReset())
|
||||
|
||||
let afterDictionary = decoder.decodeObjectDictionaryForKey("i") as [TestKey : TestParent]
|
||||
XCTAssert(afterDictionary == beforeDictionary, "object dictionary failed")
|
||||
|
||||
let afterArray = decoder.decodeObjectArrayForKey("h") as [TestParent]
|
||||
XCTAssert(afterArray == beforeArray, "object array failed")
|
||||
|
||||
XCTAssert(decoder.decodeInt64ArrayForKey("g") == [1, 2, 3, 4], "int64 array failed")
|
||||
XCTAssert(decoder.decodeInt32ArrayForKey("f") == [1, 2, 3, 4], "int32 array failed")
|
||||
|
||||
if let after = decoder.decodeObjectForKey("e") as? TestObject {
|
||||
XCTAssert(after == before, "object failed")
|
||||
} else {
|
||||
XCTFail("object failed")
|
||||
}
|
||||
|
||||
XCTAssert(decoder.decodeStringForKey("d") == "test", "string failed")
|
||||
XCTAssert(decoder.decodeBoolForKey("c"), "bool failed")
|
||||
XCTAssert(decoder.decodeInt64ForKey("b") == Int64(12345), "int64 failed")
|
||||
XCTAssert(decoder.decodeInt32ForKey("a") == 12345, "int32 failed")
|
||||
}
|
||||
}
|
@ -1,36 +1,663 @@
|
||||
//
|
||||
// PostboxTests.swift
|
||||
// PostboxTests
|
||||
//
|
||||
// Created by Peter on 10/06/15.
|
||||
// Copyright (c) 2015 Telegram. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import XCTest
|
||||
|
||||
import Postbox
|
||||
|
||||
enum TestPeerNamespace: PeerId.Namespace {
|
||||
case User = 0
|
||||
}
|
||||
|
||||
enum TestMessageNamespace: MessageId.Namespace {
|
||||
case Cloud = 0
|
||||
case Local = 1
|
||||
}
|
||||
|
||||
enum TestMediaNamespace: MediaId.Namespace {
|
||||
case Test = 0
|
||||
}
|
||||
|
||||
class TestMessage: Message {
|
||||
var id: MessageId
|
||||
var authorId: PeerId
|
||||
var date: Int32
|
||||
var text: String
|
||||
var referencedMediaIds: [MediaId]
|
||||
|
||||
var timestamp: Int32 {
|
||||
return date
|
||||
}
|
||||
|
||||
init(id: MessageId, authorId: PeerId, date: Int32, text: String, referencedMediaIds: [MediaId]) {
|
||||
self.id = id
|
||||
self.authorId = authorId
|
||||
self.date = date
|
||||
self.text = text
|
||||
self.referencedMediaIds = referencedMediaIds
|
||||
}
|
||||
|
||||
required init(decoder: Decoder) {
|
||||
self.id = MessageId(decoder.decodeBytesForKeyNoCopy("id"))
|
||||
self.authorId = PeerId(decoder.decodeInt64ForKey("authorId"))
|
||||
self.date = decoder.decodeInt32ForKey("date")
|
||||
self.text = decoder.decodeStringForKey("text")
|
||||
self.referencedMediaIds = MediaId.decodeArrayFromBuffer(decoder.decodeBytesForKeyNoCopy("mediaIds"))
|
||||
}
|
||||
|
||||
func encode(encoder: Encoder) {
|
||||
let buffer = WriteBuffer()
|
||||
self.id.encodeToBuffer(buffer)
|
||||
encoder.encodeBytes(buffer, forKey: "id")
|
||||
buffer.reset()
|
||||
|
||||
encoder.encodeInt64(self.authorId.toInt64(), forKey: "authorId")
|
||||
encoder.encodeInt32(self.date, forKey: "date")
|
||||
encoder.encodeString(self.text, forKey: "text")
|
||||
|
||||
MediaId.encodeArrayToBuffer(self.referencedMediaIds, buffer: buffer)
|
||||
encoder.encodeBytes(buffer, forKey: "mediaIds")
|
||||
buffer.reset()
|
||||
}
|
||||
}
|
||||
|
||||
class TestMedia: Media {
|
||||
var id: MediaId
|
||||
|
||||
init(id: MediaId) {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
required init(decoder: Decoder) {
|
||||
self.id = MediaId(decoder.decodeBytesForKeyNoCopy("id"))
|
||||
}
|
||||
|
||||
func encode(encoder: Encoder) {
|
||||
let buffer = WriteBuffer()
|
||||
self.id.encodeToBuffer(buffer)
|
||||
encoder.encodeBytes(buffer, forKey: "id")
|
||||
}
|
||||
}
|
||||
|
||||
class PostboxTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
XCTAssert(true, "Pass")
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
self.measureBlock() {
|
||||
// Put the code you want to measure the time of here.
|
||||
func testAddMessages() {
|
||||
declareEncodable(TestMessage.self, { TestMessage(decoder: $0) })
|
||||
declareEncodable(TestMedia.self, { TestMedia(decoder: $0) })
|
||||
|
||||
let ownerId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 1000)
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
let messageNamespace = TestMessageNamespace.Cloud.rawValue
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespace])
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 0 ..< 10 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
return
|
||||
}
|
||||
postbox._dumpTables()
|
||||
|
||||
postbox.modify { state in
|
||||
var messageIds: [MessageId] = []
|
||||
for i in 0 ..< 5 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
|
||||
messageIds.append(messageId)
|
||||
}
|
||||
state.deleteMessagesWithIds(messageIds)
|
||||
}
|
||||
postbox._dumpTables();
|
||||
|
||||
postbox.modify { state in
|
||||
var messageIds: [MessageId] = []
|
||||
for i in 0 ..< 10 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
|
||||
messageIds.append(messageId)
|
||||
}
|
||||
state.deleteMessagesWithIds(messageIds)
|
||||
}
|
||||
postbox._dumpTables();
|
||||
}
|
||||
|
||||
func testMessageNamespaceViewAddTail() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [:], messages: [], later: [:])
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
/*func assertIds(earlier: Int32?, ids: [Int32], later: Int32?) {
|
||||
let otherMessages = ids.reverse().map({ id -> Message in
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(id))
|
||||
let message = TestMessage(id: messageId, authorId: otherId, date: Int32(0), text: "", referencedMediaIds: [])
|
||||
return message
|
||||
})
|
||||
let otherView = MessageNamespaceView(namespace: messageNamespace, messages: otherMessages, earlierId: earlier, laterId: later, count: 2)
|
||||
|
||||
XCTAssert(view == otherView, "\(view) != \(otherView)")
|
||||
}*/
|
||||
|
||||
add(message(1, 90, 90))
|
||||
add(message(2, 70, 70))
|
||||
|
||||
add(message(1, 70, 70))
|
||||
|
||||
add(message(1, 80, 80))
|
||||
add(message(2, 100, 100))
|
||||
|
||||
add(message(1, 75, 75))
|
||||
|
||||
add(message(1, 60, 60))
|
||||
}
|
||||
|
||||
func testMessageNamespaceViewAddMiddle1() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [1: message(1, 90, 90)], messages: [message(1, 100, 100), message(1, 120, 120), message(1, 140, 140)], later: [1: message(1, 200, 200)])
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
add(message(2, 105, 105))
|
||||
add(message(2, 150, 150))
|
||||
add(message(2, 250, 250))
|
||||
add(message(2, 180, 180))
|
||||
}
|
||||
|
||||
func testMessageNamespaceRemoveTail() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
var messages: [Message] = []
|
||||
|
||||
func print(messages: [Message]) {
|
||||
var string = ""
|
||||
string += "["
|
||||
var first = true
|
||||
for message in messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
println(string)
|
||||
}
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [:], messages: [], later: [:])
|
||||
|
||||
func id(namespace: Int32, id: Int32) -> MessageId {
|
||||
return MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
}
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)")
|
||||
|
||||
messages.append(message)
|
||||
messages.sort({MessageIndex($0) < MessageIndex($1)})
|
||||
|
||||
print(messages)
|
||||
println()
|
||||
}
|
||||
|
||||
func remove(ids: Set<MessageId>) -> MutableMessageView.RemoveContext {
|
||||
let context = view.remove(ids)
|
||||
println("\(view)")
|
||||
|
||||
messages = messages.filter { !ids.contains($0.id) }
|
||||
print(messages)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func fetchEarlier(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = messages.count - 1
|
||||
while i >= 0 && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id < id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func fetchLater(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = 0
|
||||
while i < messages.count && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id > id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func complete(context: MutableMessageView.RemoveContext) {
|
||||
view.complete(context, fetchEarlier: fetchEarlier(messages), fetchLater: fetchLater(messages))
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
add(message(1, 90, 90))
|
||||
add(message(2, 70, 70))
|
||||
add(message(1, 70, 70))
|
||||
add(message(1, 80, 80))
|
||||
add(message(2, 100, 100))
|
||||
add(message(1, 75, 75))
|
||||
add(message(1, 60, 60))
|
||||
|
||||
println("remove 1:90, 2:100")
|
||||
complete(remove([id(1, 90), id(2, 100)]))
|
||||
|
||||
println("remove 1:60, 2:70")
|
||||
complete(remove([id(1, 60), id(2, 70)]))
|
||||
|
||||
println("remove 1:80, 2:100")
|
||||
complete(remove([id(1, 80), id(2, 100)]))
|
||||
}
|
||||
|
||||
func testMessageNamespaceRemoveAllInside() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
var messages: [Message] = []
|
||||
|
||||
func print(messages: [Message]) {
|
||||
var string = ""
|
||||
string += "["
|
||||
var first = true
|
||||
for message in messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
println(string)
|
||||
}
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [:], messages: [], later: [:])
|
||||
|
||||
func id(namespace: Int32, id: Int32) -> MessageId {
|
||||
return MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
}
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)")
|
||||
|
||||
messages.append(message)
|
||||
messages.sort({MessageIndex($0) < MessageIndex($1)})
|
||||
|
||||
print(messages)
|
||||
println()
|
||||
}
|
||||
|
||||
func remove(ids: Set<MessageId>) -> MutableMessageView.RemoveContext {
|
||||
let context = view.remove(ids)
|
||||
println("\(view)")
|
||||
|
||||
messages = messages.filter { !ids.contains($0.id) }
|
||||
print(messages)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func fetchEarlier(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = messages.count - 1
|
||||
while i >= 0 && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id < id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func fetchLater(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = 0
|
||||
while i < messages.count && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id > id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func complete(context: MutableMessageView.RemoveContext) {
|
||||
view.complete(context, fetchEarlier: fetchEarlier(messages), fetchLater: fetchLater(messages))
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
add(message(2, 10, 10))
|
||||
add(message(2, 20, 20))
|
||||
add(message(1, 90, 90))
|
||||
add(message(2, 70, 70))
|
||||
add(message(1, 70, 70))
|
||||
add(message(1, 80, 80))
|
||||
add(message(2, 100, 100))
|
||||
add(message(1, 75, 75))
|
||||
add(message(1, 60, 60))
|
||||
|
||||
println("remove 2:20, 1:80, 1:90, 2:100")
|
||||
complete(remove([id(2, 20), id(1, 80), id(1, 90), id(2, 100)]))
|
||||
}
|
||||
|
||||
func testMessageNamespaceRemoveMiddleSome() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
var messages: [Message] = []
|
||||
|
||||
func print(messages: [Message]) {
|
||||
var string = ""
|
||||
string += "["
|
||||
var first = true
|
||||
for message in messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
println(string)
|
||||
}
|
||||
|
||||
func id(namespace: Int32, id: Int32) -> MessageId {
|
||||
return MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
}
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
messages = [message(2, 1, 1), message(2, 2, 2), message(1, 98, 98), message(1, 99, 99), message(1, 100, 100), message(2, 101, 101), message(1, 102, 102), message(1, 103, 103), message(1, 104, 104), message(1, 105, 105), message(2, 200, 200), message(2, 300, 300)]
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [1: message(1, 99, 99), 2: message(2, 2, 2)], messages: [message(1, 100, 100), message(2, 101, 101), message(1, 102, 102)], later: [1: message(1, 103, 103), 2: message(2, 200, 200)])
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)")
|
||||
|
||||
messages.append(message)
|
||||
messages.sort({MessageIndex($0) < MessageIndex($1)})
|
||||
|
||||
print(messages)
|
||||
println()
|
||||
}
|
||||
|
||||
func remove(ids: Set<MessageId>) -> MutableMessageView.RemoveContext {
|
||||
let context = view.remove(ids)
|
||||
println("\(view)")
|
||||
|
||||
messages = messages.filter { !ids.contains($0.id) }
|
||||
print(messages)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func fetchEarlier(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = messages.count - 1
|
||||
while i >= 0 && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id < id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func fetchLater(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = 0
|
||||
while i < messages.count && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id > id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func complete(context: MutableMessageView.RemoveContext) {
|
||||
view.complete(context, fetchEarlier: fetchEarlier(messages), fetchLater: fetchLater(messages))
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
print(messages)
|
||||
println("\(view)")
|
||||
|
||||
println("remove 1:100, 2:101")
|
||||
complete(remove([id(1, 100), id(2, 101)]))
|
||||
}
|
||||
|
||||
func testMessageNamespaceRemoveMiddleAllInside() {
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
var messages: [Message] = []
|
||||
|
||||
func print(messages: [Message]) {
|
||||
var string = ""
|
||||
string += "["
|
||||
var first = true
|
||||
for message in messages {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "\(message.id.namespace): \(message.id.id)—\(message.timestamp)"
|
||||
}
|
||||
string += "]"
|
||||
println(string)
|
||||
}
|
||||
|
||||
func id(namespace: Int32, id: Int32) -> MessageId {
|
||||
return MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
}
|
||||
|
||||
func message(namespace: Int32, id: Int32, timestamp: Int32) -> Message {
|
||||
let messageId = MessageId(peerId: otherId, namespace: namespace, id: Int32(id))
|
||||
return TestMessage(id: messageId, authorId: otherId, date: Int32(timestamp), text: "", referencedMediaIds: [])
|
||||
}
|
||||
|
||||
messages = [message(2, 1, 1), message(2, 2, 2), message(1, 98, 98), message(1, 99, 99), message(1, 100, 100), message(2, 101, 101), message(1, 102, 102), message(1, 103, 103), message(1, 104, 104), message(1, 105, 105), message(2, 200, 200), message(2, 300, 300)]
|
||||
|
||||
let view = MutableMessageView(namespaces: [1, 2], count: 3, earlier: [1: message(1, 99, 99), 2: message(2, 2, 2)], messages: [message(1, 100, 100), message(2, 101, 101), message(1, 102, 102)], later: [1: message(1, 103, 103), 2: message(2, 200, 200)])
|
||||
|
||||
func add(message: Message) {
|
||||
view.add(message)
|
||||
println("\(view)")
|
||||
|
||||
messages.append(message)
|
||||
messages.sort({MessageIndex($0) < MessageIndex($1)})
|
||||
|
||||
print(messages)
|
||||
println()
|
||||
}
|
||||
|
||||
func remove(ids: Set<MessageId>) -> MutableMessageView.RemoveContext {
|
||||
let context = view.remove(ids)
|
||||
println("\(view)")
|
||||
|
||||
messages = messages.filter { !ids.contains($0.id) }
|
||||
print(messages)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func fetchEarlier(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = messages.count - 1
|
||||
while i >= 0 && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id < id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func fetchLater(messages: [Message])(namespace: MessageId.Namespace, id: MessageId.Id?, count: Int) -> [Message] {
|
||||
var filtered: [Message] = []
|
||||
var i = 0
|
||||
while i < messages.count && filtered.count < count {
|
||||
if messages[i].id.namespace == namespace && (id == nil || messages[i].id.id > id!) {
|
||||
filtered.append(messages[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func complete(context: MutableMessageView.RemoveContext) {
|
||||
view.complete(context, fetchEarlier: fetchEarlier(messages), fetchLater: fetchLater(messages))
|
||||
println("\(view)\n")
|
||||
}
|
||||
|
||||
print(messages)
|
||||
println("\(view)\n")
|
||||
|
||||
println("remove 1:100, 2:101, 1: 102")
|
||||
complete(remove([id(1, 100), id(2, 101), id(1, 102)]))
|
||||
}
|
||||
|
||||
func testViewTail() {
|
||||
declareEncodable(TestMessage.self, { TestMessage(decoder: $0) })
|
||||
declareEncodable(TestMedia.self, { TestMedia(decoder: $0) })
|
||||
|
||||
let ownerId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 1000)
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
let messageNamespace = TestMessageNamespace.Cloud.rawValue
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespace])
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 0 ..< 10 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
postbox.tailMessageViewForPeerId(otherId, count: 4).start(next: { next in
|
||||
println(next)
|
||||
})
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 10 ..< 15 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
postbox._sync()
|
||||
}
|
||||
|
||||
func testViewAround() {
|
||||
declareEncodable(TestMessage.self, { TestMessage(decoder: $0) })
|
||||
declareEncodable(TestMedia.self, { TestMedia(decoder: $0) })
|
||||
|
||||
let ownerId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 1000)
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
let messageNamespaceCloud = TestMessageNamespace.Cloud.rawValue
|
||||
let messageNamespaceLocal = TestMessageNamespace.Local.rawValue
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespaceCloud, messageNamespaceLocal])
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 0 ..< 10 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
for i in 10 ..< 12 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceLocal, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var i = 1000
|
||||
postbox.aroundMessageViewForPeerId(otherId, id: MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1)), count: 3).start(next: { next in
|
||||
println(next)
|
||||
})
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 10 ..< 15 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1))
|
||||
let message = TestMessage(id: messageId, authorId: ownerId, date: Int32(i + 100), text: "\(i)", referencedMediaIds: [testMedia.id])
|
||||
state.addMessages([message, message], medias: [testMedia])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
postbox._sync()
|
||||
}
|
||||
}
|
||||
|
1
submodules/sqlite.swift
Submodule
1
submodules/sqlite.swift
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit fde8c3391b265eb34b6407e3665160fb981b6857
|
Loading…
x
Reference in New Issue
Block a user