mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
no message
This commit is contained in:
parent
0eb6029dc9
commit
efe9ee147d
@ -12,11 +12,6 @@
|
|||||||
D0079F631D5A242500A27A2C /* ContactPeerIdsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F621D5A242500A27A2C /* ContactPeerIdsView.swift */; };
|
D0079F631D5A242500A27A2C /* ContactPeerIdsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F621D5A242500A27A2C /* ContactPeerIdsView.swift */; };
|
||||||
D0079F651D5A457A00A27A2C /* ContactPeersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F641D5A457A00A27A2C /* ContactPeersView.swift */; };
|
D0079F651D5A457A00A27A2C /* ContactPeersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F641D5A457A00A27A2C /* ContactPeersView.swift */; };
|
||||||
D0079F6B1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F6A1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift */; };
|
D0079F6B1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0079F6A1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift */; };
|
||||||
D00E0FB81B85D192002E4EB5 /* lmdb.h in Headers */ = {isa = PBXBuildFile; fileRef = D00E0FB41B85D192002E4EB5 /* lmdb.h */; };
|
|
||||||
D00E0FB91B85D192002E4EB5 /* mdb.c in Sources */ = {isa = PBXBuildFile; fileRef = D00E0FB51B85D192002E4EB5 /* mdb.c */; settings = {COMPILER_FLAGS = "-Wno-conversion -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-format-extra-args -Wno-macro-redefined"; }; };
|
|
||||||
D00E0FBA1B85D192002E4EB5 /* midl.c in Sources */ = {isa = PBXBuildFile; fileRef = D00E0FB61B85D192002E4EB5 /* midl.c */; settings = {COMPILER_FLAGS = "-Wno-conversion"; }; };
|
|
||||||
D00E0FBB1B85D192002E4EB5 /* midl.h in Headers */ = {isa = PBXBuildFile; fileRef = D00E0FB71B85D192002E4EB5 /* midl.h */; };
|
|
||||||
D00E0FBE1B85D1B5002E4EB5 /* LmdbValueBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00E0FBD1B85D1B5002E4EB5 /* LmdbValueBox.swift */; };
|
|
||||||
D00EED1E1C81F28D00341DFF /* MessageHistoryTagsTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00EED1D1C81F28D00341DFF /* MessageHistoryTagsTable.swift */; };
|
D00EED1E1C81F28D00341DFF /* MessageHistoryTagsTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00EED1D1C81F28D00341DFF /* MessageHistoryTagsTable.swift */; };
|
||||||
D01F7D9B1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F7D9A1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift */; };
|
D01F7D9B1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F7D9A1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift */; };
|
||||||
D01F7D9D1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F7D9C1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift */; };
|
D01F7D9D1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F7D9C1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift */; };
|
||||||
@ -109,11 +104,6 @@
|
|||||||
D0079F621D5A242500A27A2C /* ContactPeerIdsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactPeerIdsView.swift; sourceTree = "<group>"; };
|
D0079F621D5A242500A27A2C /* ContactPeerIdsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactPeerIdsView.swift; sourceTree = "<group>"; };
|
||||||
D0079F641D5A457A00A27A2C /* ContactPeersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactPeersView.swift; sourceTree = "<group>"; };
|
D0079F641D5A457A00A27A2C /* ContactPeersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactPeersView.swift; sourceTree = "<group>"; };
|
||||||
D0079F6A1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerNameIndexRepresentation.swift; sourceTree = "<group>"; };
|
D0079F6A1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerNameIndexRepresentation.swift; sourceTree = "<group>"; };
|
||||||
D00E0FB41B85D192002E4EB5 /* lmdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lmdb.h; path = submodules/lmdb/libraries/liblmdb/lmdb.h; sourceTree = SOURCE_ROOT; };
|
|
||||||
D00E0FB51B85D192002E4EB5 /* mdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mdb.c; path = submodules/lmdb/libraries/liblmdb/mdb.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
D00E0FB61B85D192002E4EB5 /* midl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = midl.c; path = submodules/lmdb/libraries/liblmdb/midl.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
D00E0FB71B85D192002E4EB5 /* midl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = midl.h; path = submodules/lmdb/libraries/liblmdb/midl.h; sourceTree = SOURCE_ROOT; };
|
|
||||||
D00E0FBD1B85D1B5002E4EB5 /* LmdbValueBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LmdbValueBox.swift; sourceTree = "<group>"; };
|
|
||||||
D00EED1D1C81F28D00341DFF /* MessageHistoryTagsTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHistoryTagsTable.swift; sourceTree = "<group>"; };
|
D00EED1D1C81F28D00341DFF /* MessageHistoryTagsTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHistoryTagsTable.swift; sourceTree = "<group>"; };
|
||||||
D01F7D9A1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHistoryInvalidatedReadStateTable.swift; sourceTree = "<group>"; };
|
D01F7D9A1CBEC390008765C9 /* MessageHistoryInvalidatedReadStateTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHistoryInvalidatedReadStateTable.swift; sourceTree = "<group>"; };
|
||||||
D01F7D9C1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePeerReadStatesView.swift; sourceTree = "<group>"; };
|
D01F7D9C1CBF8586008765C9 /* SynchronizePeerReadStatesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePeerReadStatesView.swift; sourceTree = "<group>"; };
|
||||||
@ -214,17 +204,6 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
D00E0FBC1B85D194002E4EB5 /* lmdb */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D00E0FB41B85D192002E4EB5 /* lmdb.h */,
|
|
||||||
D00E0FB51B85D192002E4EB5 /* mdb.c */,
|
|
||||||
D00E0FB61B85D192002E4EB5 /* midl.c */,
|
|
||||||
D00E0FB71B85D192002E4EB5 /* midl.h */,
|
|
||||||
);
|
|
||||||
name = lmdb;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D05F09981C9CAC1100BB6F96 /* Media Box */ = {
|
D05F09981C9CAC1100BB6F96 /* Media Box */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -240,7 +219,6 @@
|
|||||||
D07515FC1B2C44A200AE42E0 /* thirdparty */ = {
|
D07515FC1B2C44A200AE42E0 /* thirdparty */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D00E0FBC1B85D194002E4EB5 /* lmdb */,
|
|
||||||
D07516731B2EC8C700AE42E0 /* sqlite.swift */,
|
D07516731B2EC8C700AE42E0 /* sqlite.swift */,
|
||||||
);
|
);
|
||||||
name = thirdparty;
|
name = thirdparty;
|
||||||
@ -337,7 +315,6 @@
|
|||||||
D0977F9D1B8234DF009994B2 /* ValueBoxKey.swift */,
|
D0977F9D1B8234DF009994B2 /* ValueBoxKey.swift */,
|
||||||
D0977F9B1B822DB4009994B2 /* ValueBox.swift */,
|
D0977F9B1B822DB4009994B2 /* ValueBox.swift */,
|
||||||
D0977F9F1B8244D7009994B2 /* SqliteValueBox.swift */,
|
D0977F9F1B8244D7009994B2 /* SqliteValueBox.swift */,
|
||||||
D00E0FBD1B85D1B5002E4EB5 /* LmdbValueBox.swift */,
|
|
||||||
);
|
);
|
||||||
name = "Value Box";
|
name = "Value Box";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -443,9 +420,7 @@
|
|||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D00E0FB81B85D192002E4EB5 /* lmdb.h in Headers */,
|
|
||||||
D07516771B2EC90400AE42E0 /* fts3_tokenizer.h in Headers */,
|
D07516771B2EC90400AE42E0 /* fts3_tokenizer.h in Headers */,
|
||||||
D00E0FBB1B85D192002E4EB5 /* midl.h in Headers */,
|
|
||||||
D07516451B2D9CEF00AE42E0 /* sqlite3.h in Headers */,
|
D07516451B2D9CEF00AE42E0 /* sqlite3.h in Headers */,
|
||||||
D0D511041D64D91C00A97B8A /* IpcNotifier.h in Headers */,
|
D0D511041D64D91C00A97B8A /* IpcNotifier.h in Headers */,
|
||||||
D07516781B2EC90400AE42E0 /* SQLite-Bridging.h in Headers */,
|
D07516781B2EC90400AE42E0 /* SQLite-Bridging.h in Headers */,
|
||||||
@ -565,7 +540,6 @@
|
|||||||
D08CEFB41D2AD8BE0015D3BC /* RedBlackTree.swift in Sources */,
|
D08CEFB41D2AD8BE0015D3BC /* RedBlackTree.swift in Sources */,
|
||||||
D044CA2E1C618373002160FF /* ChatListHole.swift in Sources */,
|
D044CA2E1C618373002160FF /* ChatListHole.swift in Sources */,
|
||||||
D044E1631B2AD677001EE087 /* MurMurHash32.m in Sources */,
|
D044E1631B2AD677001EE087 /* MurMurHash32.m in Sources */,
|
||||||
D00E0FBE1B85D1B5002E4EB5 /* LmdbValueBox.swift in Sources */,
|
|
||||||
D0079F6B1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift in Sources */,
|
D0079F6B1D5B3AAB00A27A2C /* PeerNameIndexRepresentation.swift in Sources */,
|
||||||
D08C713A1C501F0700779C0F /* MessageHistoryHole.swift in Sources */,
|
D08C713A1C501F0700779C0F /* MessageHistoryHole.swift in Sources */,
|
||||||
D044CA2A1C617D39002160FF /* SeedConfiguration.swift in Sources */,
|
D044CA2A1C617D39002160FF /* SeedConfiguration.swift in Sources */,
|
||||||
@ -583,7 +557,6 @@
|
|||||||
D0C9DA391C65782500855278 /* SimpleSet.swift in Sources */,
|
D0C9DA391C65782500855278 /* SimpleSet.swift in Sources */,
|
||||||
D0977F9E1B8234DF009994B2 /* ValueBoxKey.swift in Sources */,
|
D0977F9E1B8234DF009994B2 /* ValueBoxKey.swift in Sources */,
|
||||||
D033A6F91C73E440006A2EAB /* UnsentMessageHistoryView.swift in Sources */,
|
D033A6F91C73E440006A2EAB /* UnsentMessageHistoryView.swift in Sources */,
|
||||||
D00E0FB91B85D192002E4EB5 /* mdb.c in Sources */,
|
|
||||||
D09ADF0C1D2EB83500C8208D /* OrderStatisticTable.swift in Sources */,
|
D09ADF0C1D2EB83500C8208D /* OrderStatisticTable.swift in Sources */,
|
||||||
D0CE63F61CA1CCB2002BC462 /* MediaResource.swift in Sources */,
|
D0CE63F61CA1CCB2002BC462 /* MediaResource.swift in Sources */,
|
||||||
D0D510F91D63BCC200A97B8A /* IntermediateMessage.swift in Sources */,
|
D0D510F91D63BCC200A97B8A /* IntermediateMessage.swift in Sources */,
|
||||||
@ -593,7 +566,6 @@
|
|||||||
D0AB0B8E1D65D49C002C78E7 /* ChatListHolesView.swift in Sources */,
|
D0AB0B8E1D65D49C002C78E7 /* ChatListHolesView.swift in Sources */,
|
||||||
D07516791B2EC90400AE42E0 /* SQLite-Bridging.m in Sources */,
|
D07516791B2EC90400AE42E0 /* SQLite-Bridging.m in Sources */,
|
||||||
D0977FA01B8244D7009994B2 /* SqliteValueBox.swift in Sources */,
|
D0977FA01B8244D7009994B2 /* SqliteValueBox.swift in Sources */,
|
||||||
D00E0FBA1B85D192002E4EB5 /* midl.c in Sources */,
|
|
||||||
D0F9E8651C58CB7F00037222 /* ChatListTable.swift in Sources */,
|
D0F9E8651C58CB7F00037222 /* ChatListTable.swift in Sources */,
|
||||||
D0F9E8711C5A0E9B00037222 /* PeerTable.swift in Sources */,
|
D0F9E8711C5A0E9B00037222 /* PeerTable.swift in Sources */,
|
||||||
D05F09A61C9E9F9300BB6F96 /* MediaResourceStatus.swift in Sources */,
|
D05F09A61C9E9F9300BB6F96 /* MediaResourceStatus.swift in Sources */,
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<key>PostboxTests.xcscheme</key>
|
<key>PostboxTests.xcscheme</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>5</integer>
|
<integer>4</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>SuppressBuildableAutocreation</key>
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class MutableChatListHolesView {
|
final class MutableChatListHolesView {
|
||||||
private var entries = Set<ChatListHole>()
|
fileprivate var entries = Set<ChatListHole>()
|
||||||
|
|
||||||
func update(holes: Set<ChatListHole>) -> Bool {
|
func update(holes: Set<ChatListHole>) -> Bool {
|
||||||
if self.entries != holes {
|
if self.entries != holes {
|
||||||
|
@ -83,7 +83,7 @@ final class ChatListTable: Table {
|
|||||||
if let topMessage = messageHistoryTable.topMessage(peerId) {
|
if let topMessage = messageHistoryTable.topMessage(peerId) {
|
||||||
let index = MessageIndex(id: topMessage.id, timestamp: topMessage.timestamp)
|
let index = MessageIndex(id: topMessage.id, timestamp: topMessage.timestamp)
|
||||||
|
|
||||||
if let currentIndex = currentIndex where currentIndex != index {
|
if let currentIndex = currentIndex , currentIndex != index {
|
||||||
self.justRemoveMessage(currentIndex)
|
self.justRemoveMessage(currentIndex)
|
||||||
}
|
}
|
||||||
if let currentIndex = currentIndex {
|
if let currentIndex = currentIndex {
|
||||||
|
@ -101,9 +101,9 @@ final class MutableChatListViewReplayContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class MutableChatListView {
|
final class MutableChatListView {
|
||||||
private var earlier: MutableChatListEntry?
|
fileprivate var earlier: MutableChatListEntry?
|
||||||
private var later: MutableChatListEntry?
|
fileprivate var later: MutableChatListEntry?
|
||||||
private var entries: [MutableChatListEntry]
|
fileprivate var entries: [MutableChatListEntry]
|
||||||
private var count: Int
|
private var count: Int
|
||||||
|
|
||||||
init(earlier: MutableChatListEntry?, entries: [MutableChatListEntry], later: MutableChatListEntry?, count: Int) {
|
init(earlier: MutableChatListEntry?, entries: [MutableChatListEntry], later: MutableChatListEntry?, count: Int) {
|
||||||
@ -113,13 +113,13 @@ final class MutableChatListView {
|
|||||||
self.count = count
|
self.count = count
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshDueToExternalTransaction(fetchAroundChatEntries: (index: MessageIndex, count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?)) -> Bool {
|
func refreshDueToExternalTransaction(fetchAroundChatEntries: (_ index: MessageIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?)) -> Bool {
|
||||||
var index = MessageIndex.absoluteUpperBound()
|
var index = MessageIndex.absoluteUpperBound()
|
||||||
if !self.entries.isEmpty {
|
if !self.entries.isEmpty {
|
||||||
index = self.entries[self.entries.count / 2].index
|
index = self.entries[self.entries.count / 2].index
|
||||||
}
|
}
|
||||||
|
|
||||||
var (entries, earlier, later) = fetchAroundChatEntries(index: index, count: self.entries.count)
|
var (entries, earlier, later) = fetchAroundChatEntries(index, self.entries.count)
|
||||||
|
|
||||||
if entries != self.entries || earlier != self.earlier || later != self.later {
|
if entries != self.entries || earlier != self.earlier || later != self.later {
|
||||||
self.entries = entries
|
self.entries = entries
|
||||||
@ -223,7 +223,7 @@ final class MutableChatListView {
|
|||||||
|
|
||||||
func remove(_ indices: Set<MessageIndex>, holes: Bool, context: MutableChatListViewReplayContext) -> Bool {
|
func remove(_ indices: Set<MessageIndex>, holes: Bool, context: MutableChatListViewReplayContext) -> Bool {
|
||||||
var hasChanges = false
|
var hasChanges = false
|
||||||
if let earlier = self.earlier where indices.contains(earlier.index) {
|
if let earlier = self.earlier , indices.contains(earlier.index) {
|
||||||
var match = false
|
var match = false
|
||||||
switch earlier {
|
switch earlier {
|
||||||
case .HoleEntry:
|
case .HoleEntry:
|
||||||
@ -237,7 +237,7 @@ final class MutableChatListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let later = self.later where indices.contains(later.index) {
|
if let later = self.later , indices.contains(later.index) {
|
||||||
var match = false
|
var match = false
|
||||||
switch later {
|
switch later {
|
||||||
case .HoleEntry:
|
case .HoleEntry:
|
||||||
|
@ -22,7 +22,7 @@ private let typeStore = { () -> EncodableTypeStore in
|
|||||||
return _typeStore
|
return _typeStore
|
||||||
}()
|
}()
|
||||||
|
|
||||||
public func declareEncodable(_ type: Any.Type, f: (Decoder) -> Coding) {
|
public func declareEncodable(_ type: Any.Type, f: @escaping(Decoder) -> Coding) {
|
||||||
let string = "\(type)"
|
let string = "\(type)"
|
||||||
let hash = murMurHashString32(string)
|
let hash = murMurHashString32(string)
|
||||||
if typeStore.dict[hash] != nil {
|
if typeStore.dict[hash] != nil {
|
||||||
@ -34,7 +34,7 @@ public func declareEncodable(_ type: Any.Type, f: (Decoder) -> Coding) {
|
|||||||
private let emptyMemory = malloc(1)!
|
private let emptyMemory = malloc(1)!
|
||||||
|
|
||||||
public class MemoryBuffer: Equatable, CustomStringConvertible {
|
public class MemoryBuffer: Equatable, CustomStringConvertible {
|
||||||
var memory: UnsafeMutablePointer<Void>
|
var memory: UnsafeMutableRawPointer
|
||||||
var capacity: Int
|
var capacity: Int
|
||||||
var length: Int
|
var length: Int
|
||||||
var freeWhenDone: Bool
|
var freeWhenDone: Bool
|
||||||
@ -47,7 +47,7 @@ public class MemoryBuffer: Equatable, CustomStringConvertible {
|
|||||||
self.freeWhenDone = true
|
self.freeWhenDone = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(memory: UnsafeMutablePointer<Void>, capacity: Int, length: Int, freeWhenDone: Bool) {
|
public init(memory: UnsafeMutableRawPointer, capacity: Int, length: Int, freeWhenDone: Bool) {
|
||||||
self.memory = memory
|
self.memory = memory
|
||||||
self.capacity = capacity
|
self.capacity = capacity
|
||||||
self.length = length
|
self.length = length
|
||||||
@ -62,7 +62,7 @@ public class MemoryBuffer: Equatable, CustomStringConvertible {
|
|||||||
self.freeWhenDone = false
|
self.freeWhenDone = false
|
||||||
} else {
|
} else {
|
||||||
self.memory = malloc(data.count)!
|
self.memory = malloc(data.count)!
|
||||||
data.copyBytes(to: UnsafeMutablePointer<UInt8>(self.memory), count: data.count)
|
data.copyBytes(to: self.memory.assumingMemoryBound(to: UInt8.self), count: data.count)
|
||||||
self.capacity = data.count
|
self.capacity = data.count
|
||||||
self.length = data.count
|
self.length = data.count
|
||||||
self.freeWhenDone = false
|
self.freeWhenDone = false
|
||||||
@ -84,7 +84,7 @@ public class MemoryBuffer: Equatable, CustomStringConvertible {
|
|||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
let hexString = NSMutableString()
|
let hexString = NSMutableString()
|
||||||
let bytes = UnsafeMutablePointer<UInt8>(self.memory)
|
let bytes = self.memory.assumingMemoryBound(to: UInt8.self)
|
||||||
for i in 0 ..< self.length {
|
for i in 0 ..< self.length {
|
||||||
hexString.appendFormat("%02x", UInt(bytes[i]))
|
hexString.appendFormat("%02x", UInt(bytes[i]))
|
||||||
}
|
}
|
||||||
@ -117,14 +117,14 @@ public final class WriteBuffer: MemoryBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func makeData() -> Data {
|
public func makeData() -> Data {
|
||||||
return Data(bytes: UnsafePointer<UInt8>(self.memory), count: self.offset)
|
return Data(bytes: self.memory.assumingMemoryBound(to: UInt8.self), count: self.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reset() {
|
public func reset() {
|
||||||
self.offset = 0
|
self.offset = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public func write(_ data: UnsafePointer<Void>, offset: Int, length: Int) {
|
public func write(_ data: UnsafeRawPointer, offset: Int, length: Int) {
|
||||||
if self.offset + length > self.capacity {
|
if self.offset + length > self.capacity {
|
||||||
self.capacity = self.offset + length + 256
|
self.capacity = self.offset + length + 256
|
||||||
if self.length == 0 {
|
if self.length == 0 {
|
||||||
@ -148,7 +148,7 @@ public final class WriteBuffer: MemoryBuffer {
|
|||||||
self.memory = realloc(self.memory, self.capacity)
|
self.memory = realloc(self.memory, self.capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.copyBytes(to: UnsafeMutablePointer<UInt8>(self.memory + offset), count: length)
|
data.copyBytes(to: self.memory.advanced(by: offset).assumingMemoryBound(to: UInt8.self), count: length)
|
||||||
self.offset += length
|
self.offset += length
|
||||||
self.length = self.offset
|
self.length = self.offset
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ public final class WriteBuffer: MemoryBuffer {
|
|||||||
public final class ReadBuffer: MemoryBuffer {
|
public final class ReadBuffer: MemoryBuffer {
|
||||||
public var offset = 0
|
public var offset = 0
|
||||||
|
|
||||||
public init(memory: UnsafeMutablePointer<Void>, length: Int, freeWhenDone: Bool) {
|
public init(memory: UnsafeMutableRawPointer, length: Int, freeWhenDone: Bool) {
|
||||||
super.init(memory: memory, capacity: length, length: length, freeWhenDone: freeWhenDone)
|
super.init(memory: memory, capacity: length, length: length, freeWhenDone: freeWhenDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,11 +166,11 @@ public final class ReadBuffer: MemoryBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func dataNoCopy() -> Data {
|
public func dataNoCopy() -> Data {
|
||||||
return Data(bytesNoCopy: UnsafeMutablePointer<UInt8>(self.memory), count: self.length, deallocator: .none)
|
return Data(bytesNoCopy: self.memory.assumingMemoryBound(to: UInt8.self), count: self.length, deallocator: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func read(_ data: UnsafeMutablePointer<Void>, offset: Int, length: Int) {
|
public func read(_ data: UnsafeMutablePointer<Void>, offset: Int, length: Int) {
|
||||||
memcpy(data + offset, self.memory + self.offset, length)
|
memcpy(data + offset, self.memory.advanced(by: self.offset), length)
|
||||||
self.offset += length
|
self.offset += length
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ public final class Encoder {
|
|||||||
var type: Int8 = ValueType.Object.rawValue
|
var type: Int8 = ValueType.Object.rawValue
|
||||||
self.buffer.write(&type, offset: 0, length: 1)
|
self.buffer.write(&type, offset: 0, length: 1)
|
||||||
|
|
||||||
let string = "\(value.dynamicType)"
|
let string = "\(type(of: value))"
|
||||||
var typeHash: Int32 = murMurHashString32(string)
|
var typeHash: Int32 = murMurHashString32(string)
|
||||||
self.buffer.write(&typeHash, offset: 0, length: 4)
|
self.buffer.write(&typeHash, offset: 0, length: 4)
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ public final class Encoder {
|
|||||||
self.buffer.write(&length, offset: 0, length: 4)
|
self.buffer.write(&length, offset: 0, length: 4)
|
||||||
let innerEncoder = Encoder()
|
let innerEncoder = Encoder()
|
||||||
for object in value {
|
for object in value {
|
||||||
var typeHash: Int32 = murMurHashString32("\(object.dynamicType)")
|
var typeHash: Int32 = murMurHashString32("\(type(of: object))")
|
||||||
self.buffer.write(&typeHash, offset: 0, length: 4)
|
self.buffer.write(&typeHash, offset: 0, length: 4)
|
||||||
|
|
||||||
innerEncoder.reset()
|
innerEncoder.reset()
|
||||||
@ -348,7 +348,7 @@ public final class Encoder {
|
|||||||
self.buffer.write(&length, offset: 0, length: 4)
|
self.buffer.write(&length, offset: 0, length: 4)
|
||||||
let innerEncoder = Encoder()
|
let innerEncoder = Encoder()
|
||||||
for object in value {
|
for object in value {
|
||||||
var typeHash: Int32 = murMurHashString32("\(object.dynamicType)")
|
var typeHash: Int32 = murMurHashString32("\(type(of: object))")
|
||||||
self.buffer.write(&typeHash, offset: 0, length: 4)
|
self.buffer.write(&typeHash, offset: 0, length: 4)
|
||||||
|
|
||||||
innerEncoder.reset()
|
innerEncoder.reset()
|
||||||
@ -369,7 +369,7 @@ public final class Encoder {
|
|||||||
|
|
||||||
let innerEncoder = Encoder()
|
let innerEncoder = Encoder()
|
||||||
for record in value {
|
for record in value {
|
||||||
var keyTypeHash: Int32 = murMurHashString32("\(record.0.dynamicType)")
|
var keyTypeHash: Int32 = murMurHashString32("\(type(of: record.0))")
|
||||||
self.buffer.write(&keyTypeHash, offset: 0, length: 4)
|
self.buffer.write(&keyTypeHash, offset: 0, length: 4)
|
||||||
innerEncoder.reset()
|
innerEncoder.reset()
|
||||||
record.0.encode(innerEncoder)
|
record.0.encode(innerEncoder)
|
||||||
@ -377,7 +377,7 @@ public final class Encoder {
|
|||||||
self.buffer.write(&keyLength, offset: 0, length: 4)
|
self.buffer.write(&keyLength, offset: 0, length: 4)
|
||||||
self.buffer.write(innerEncoder.buffer.memory, offset: 0, length: Int(keyLength))
|
self.buffer.write(innerEncoder.buffer.memory, offset: 0, length: Int(keyLength))
|
||||||
|
|
||||||
var valueTypeHash: Int32 = murMurHashString32("\(record.1.dynamicType)")
|
var valueTypeHash: Int32 = murMurHashString32("\(type(of: record.1))")
|
||||||
self.buffer.write(&valueTypeHash, offset: 0, length: 4)
|
self.buffer.write(&valueTypeHash, offset: 0, length: 4)
|
||||||
innerEncoder.reset()
|
innerEncoder.reset()
|
||||||
record.1.encode(innerEncoder)
|
record.1.encode(innerEncoder)
|
||||||
@ -484,8 +484,10 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class func positionOnKey(_ bytes: UnsafePointer<Int8>, offset: inout Int, maxOffset: Int, length: Int, key: StaticString, valueType: ValueType) -> Bool
|
private class func positionOnKey(_ rawBytes: UnsafeRawPointer, offset: inout Int, maxOffset: Int, length: Int, key: StaticString, valueType: ValueType) -> Bool
|
||||||
{
|
{
|
||||||
|
let bytes = rawBytes.assumingMemoryBound(to: Int8.self)
|
||||||
|
|
||||||
let startOffset = offset
|
let startOffset = offset
|
||||||
|
|
||||||
let keyLength: Int = key.utf8CodeUnitCount
|
let keyLength: Int = key.utf8CodeUnitCount
|
||||||
@ -546,7 +548,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt32ForKey(_ key: StaticString) -> Int32 {
|
public func decodeInt32ForKey(_ key: StaticString) -> Int32 {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
|
||||||
var value: Int32 = 0
|
var value: Int32 = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 4)
|
memcpy(&value, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -557,7 +559,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt32ForKey(_ key: StaticString) -> Int32? {
|
public func decodeInt32ForKey(_ key: StaticString) -> Int32? {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
|
||||||
var value: Int32 = 0
|
var value: Int32 = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 4)
|
memcpy(&value, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -568,7 +570,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt64ForKey(_ key: StaticString) -> Int64 {
|
public func decodeInt64ForKey(_ key: StaticString) -> Int64 {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64) {
|
||||||
var value: Int64 = 0
|
var value: Int64 = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 8)
|
memcpy(&value, self.buffer.memory + self.offset, 8)
|
||||||
self.offset += 8
|
self.offset += 8
|
||||||
@ -579,7 +581,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt64ForKey(_ key: StaticString) -> Int64? {
|
public func decodeInt64ForKey(_ key: StaticString) -> Int64? {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64) {
|
||||||
var value: Int64 = 0
|
var value: Int64 = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 8)
|
memcpy(&value, self.buffer.memory + self.offset, 8)
|
||||||
self.offset += 8
|
self.offset += 8
|
||||||
@ -590,7 +592,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeBoolForKey(_ key: StaticString) -> Bool {
|
public func decodeBoolForKey(_ key: StaticString) -> Bool {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Bool) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Bool) {
|
||||||
var value: Int8 = 0
|
var value: Int8 = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 1)
|
memcpy(&value, self.buffer.memory + self.offset, 1)
|
||||||
self.offset += 1
|
self.offset += 1
|
||||||
@ -601,7 +603,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeDoubleForKey(_ key: StaticString) -> Double {
|
public func decodeDoubleForKey(_ key: StaticString) -> Double {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Double) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Double) {
|
||||||
var value: Double = 0
|
var value: Double = 0
|
||||||
memcpy(&value, self.buffer.memory + self.offset, 8)
|
memcpy(&value, self.buffer.memory + self.offset, 8)
|
||||||
self.offset += 8
|
self.offset += 8
|
||||||
@ -612,10 +614,10 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeStringForKey(_ key: StaticString) -> String {
|
public func decodeStringForKey(_ key: StaticString) -> String {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .String) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .String) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
let data = Data(bytes: UnsafeMutablePointer<UInt8>(self.buffer.memory).advanced(by: self.offset + 4), count: Int(length))
|
let data = Data(bytes: self.buffer.memory.assumingMemoryBound(to: UInt8.self).advanced(by: self.offset + 4), count: Int(length))
|
||||||
self.offset += 4 + Int(length)
|
self.offset += 4 + Int(length)
|
||||||
return String(data: data, encoding: .utf8) ?? ""
|
return String(data: data, encoding: .utf8) ?? ""
|
||||||
} else {
|
} else {
|
||||||
@ -624,10 +626,10 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeStringForKey(_ key: StaticString) -> String? {
|
public func decodeStringForKey(_ key: StaticString) -> String? {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .String) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .String) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
let data = Data(bytes: UnsafeMutablePointer<UInt8>(self.buffer.memory).advanced(by: self.offset + 4), count: Int(length))
|
let data = Data(bytes: self.buffer.memory.assumingMemoryBound(to: UInt8.self).advanced(by: self.offset + 4), count: Int(length))
|
||||||
self.offset += 4 + Int(length)
|
self.offset += 4 + Int(length)
|
||||||
return String(data: data, encoding: .utf8)
|
return String(data: data, encoding: .utf8)
|
||||||
} else {
|
} else {
|
||||||
@ -640,7 +642,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectForKey(_ key: StaticString) -> Coding? {
|
public func decodeObjectForKey(_ key: StaticString) -> Coding? {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
|
||||||
var typeHash: Int32 = 0
|
var typeHash: Int32 = 0
|
||||||
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
|
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -658,7 +660,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectForKey(_ key: StaticString, decoder: (Decoder) -> Coding) -> Coding? {
|
public func decodeObjectForKey(_ key: StaticString, decoder: (Decoder) -> Coding) -> Coding? {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
|
||||||
var typeHash: Int32 = 0
|
var typeHash: Int32 = 0
|
||||||
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
|
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -676,7 +678,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt32ArrayForKey(_ key: StaticString) -> [Int32] {
|
public func decodeInt32ArrayForKey(_ key: StaticString) -> [Int32] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32Array) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32Array) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
var array: [Int32] = []
|
var array: [Int32] = []
|
||||||
@ -696,7 +698,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeInt64ArrayForKey(_ key: StaticString) -> [Int64] {
|
public func decodeInt64ArrayForKey(_ key: StaticString) -> [Int64] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64Array) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int64Array) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
var array: [Int64] = []
|
var array: [Int64] = []
|
||||||
@ -716,7 +718,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectArrayWithDecoderForKey<T where T: Coding>(_ key: StaticString) -> [T] {
|
public func decodeObjectArrayWithDecoderForKey<T where T: Coding>(_ key: StaticString) -> [T] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -755,7 +757,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectArrayForKey<T where T: Coding>(_ key: StaticString) -> [T] {
|
public func decodeObjectArrayForKey<T where T: Coding>(_ key: StaticString) -> [T] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -798,7 +800,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectArrayForKey(_ key: StaticString) -> [Coding] {
|
public func decodeObjectArrayForKey(_ key: StaticString) -> [Coding] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectArray) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -841,7 +843,7 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeObjectDictionaryForKey<K, V: Coding where K: Coding, K: Hashable>(_ key: StaticString) -> [K : V] {
|
public func decodeObjectDictionaryForKey<K, V: Coding where K: Coding, K: Hashable>(_ key: StaticString) -> [K : V] {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectDictionary) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectDictionary) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4
|
self.offset += 4
|
||||||
@ -875,7 +877,7 @@ public final class Decoder {
|
|||||||
|
|
||||||
let value = failed ? nil : (typeStore.decode(valueHash, decoder: innerDecoder) as? V)
|
let value = failed ? nil : (typeStore.decode(valueHash, decoder: innerDecoder) as? V)
|
||||||
|
|
||||||
if let key = key, value = value {
|
if let key = key, let value = value {
|
||||||
dictionary[key] = value
|
dictionary[key] = value
|
||||||
} else {
|
} else {
|
||||||
failed = true
|
failed = true
|
||||||
@ -895,11 +897,11 @@ public final class Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func decodeBytesForKeyNoCopy(_ key: StaticString) -> ReadBuffer! {
|
public func decodeBytesForKeyNoCopy(_ key: StaticString) -> ReadBuffer! {
|
||||||
if Decoder.positionOnKey(UnsafePointer<Int8>(self.buffer.memory), offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Bytes) {
|
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Bytes) {
|
||||||
var length: Int32 = 0
|
var length: Int32 = 0
|
||||||
memcpy(&length, self.buffer.memory + self.offset, 4)
|
memcpy(&length, self.buffer.memory + self.offset, 4)
|
||||||
self.offset += 4 + Int(length)
|
self.offset += 4 + Int(length)
|
||||||
return ReadBuffer(memory: UnsafeMutablePointer<Int8>(self.buffer.memory + (self.offset - Int(length))), length: Int(length), freeWhenDone: false)
|
return ReadBuffer(memory: self.buffer.memory.advanced(by: self.offset - Int(length)), length: Int(length), freeWhenDone: false)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class MutableContactPeerIdsView {
|
final class MutableContactPeerIdsView {
|
||||||
private var peerIds: Set<PeerId>
|
fileprivate var peerIds: Set<PeerId>
|
||||||
|
|
||||||
init(peerIds: Set<PeerId>) {
|
init(peerIds: Set<PeerId>) {
|
||||||
self.peerIds = peerIds
|
self.peerIds = peerIds
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class MutableContactPeersView {
|
final class MutableContactPeersView {
|
||||||
private let index: PeerNameIndex
|
fileprivate let index: PeerNameIndex
|
||||||
private var peers: [PeerId: Peer]
|
fileprivate var peers: [PeerId: Peer]
|
||||||
private var peerIds: Set<PeerId>
|
fileprivate var peerIds: Set<PeerId>
|
||||||
private var accountPeer: Peer?
|
fileprivate var accountPeer: Peer?
|
||||||
|
|
||||||
init(peers: [PeerId: Peer], index: PeerNameIndex, accountPeer: Peer?) {
|
init(peers: [PeerId: Peer], index: PeerNameIndex, accountPeer: Peer?) {
|
||||||
self.index = index
|
self.index = index
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
@interface RLMNotifier : NSObject
|
@interface RLMNotifier : NSObject
|
||||||
|
|
||||||
- (instancetype)initWithBasePath:(NSString *)basePath notify:(void (^)())notify;
|
- (instancetype _Nonnull)initWithBasePath:(NSString * _Nonnull)basePath notify:(void (^ _Nonnull)())notify;
|
||||||
- (void)listen;
|
- (void)listen;
|
||||||
- (void)notifyOtherRealms;
|
- (void)notifyOtherRealms;
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ namespace {
|
|||||||
FdHolder _shutdownWriteFd;
|
FdHolder _shutdownWriteFd;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithBasePath:(NSString *)basePath notify:(void (^)())notify {
|
- (instancetype)initWithBasePath:(NSString *)basePath notify:( void (^ _Nonnull)())notify {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_notify = [notify copy];
|
_notify = [notify copy];
|
||||||
|
@ -11,7 +11,7 @@ final class KeychainTable: Table {
|
|||||||
|
|
||||||
func get(_ key: String) -> Data? {
|
func get(_ key: String) -> Data? {
|
||||||
if let value = self.valueBox.get(self.tableId, key: self.key(key)) {
|
if let value = self.valueBox.get(self.tableId, key: self.key(key)) {
|
||||||
return Data(bytes: UnsafePointer<UInt8>(value.memory), count: value.length)
|
return Data(bytes: value.memory.assumingMemoryBound(to: UInt8.self), count: value.length)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,451 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import sqlcipher
|
|
||||||
|
|
||||||
private struct LmdbTable {
|
|
||||||
var dbi: MDB_dbi
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct LmdbCursor {
|
|
||||||
var cursor: OpaquePointer!
|
|
||||||
|
|
||||||
func seekTo(_ key: ValueBoxKey, forward: Bool) -> (ValueBoxKey, ReadBuffer)? {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
var mdbData = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = key.memory
|
|
||||||
mdbKey.mv_size = key.length
|
|
||||||
mdbData.mv_data = nil
|
|
||||||
mdbData.mv_size = 0
|
|
||||||
|
|
||||||
let result = mdb_cursor_get(self.cursor, &mdbKey, &mdbData, forward ? MDB_SET_RANGE : MDB_SET_KEY)
|
|
||||||
|
|
||||||
if result == MDB_SUCCESS {
|
|
||||||
let actualKey = ValueBoxKey(length: mdbKey.mv_size)
|
|
||||||
memcpy(actualKey.memory, mdbKey.mv_data, mdbKey.mv_size)
|
|
||||||
|
|
||||||
let value = malloc(mdbData.mv_size)!
|
|
||||||
memcpy(value, mdbData.mv_data, mdbData.mv_size)
|
|
||||||
|
|
||||||
return (actualKey, ReadBuffer(memory: value, length: mdbData.mv_size, freeWhenDone: true))
|
|
||||||
} else if result == MDB_NOTFOUND {
|
|
||||||
if !forward {
|
|
||||||
return self.previous()
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print("(LmdbValueBox mdb_cursor_get failed with \(result))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func previous() -> (ValueBoxKey, ReadBuffer)? {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
var mdbData = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = nil
|
|
||||||
mdbKey.mv_size = 0
|
|
||||||
mdbData.mv_data = nil
|
|
||||||
mdbData.mv_size = 0
|
|
||||||
|
|
||||||
let result = mdb_cursor_get(self.cursor, &mdbKey, &mdbData, MDB_PREV)
|
|
||||||
if result == MDB_SUCCESS {
|
|
||||||
let actualKey = ValueBoxKey(length: mdbKey.mv_size)
|
|
||||||
memcpy(actualKey.memory, mdbKey.mv_data, mdbKey.mv_size)
|
|
||||||
|
|
||||||
let value = malloc(mdbData.mv_size)!
|
|
||||||
memcpy(value, mdbData.mv_data, mdbData.mv_size)
|
|
||||||
|
|
||||||
return (actualKey, ReadBuffer(memory: value, length: mdbData.mv_size, freeWhenDone: true))
|
|
||||||
} else if result == MDB_NOTFOUND {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
print("(LmdbValueBox mdb_cursor_get failed with \(result))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func next() -> (ValueBoxKey, ReadBuffer)? {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
var mdbData = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = nil
|
|
||||||
mdbKey.mv_size = 0
|
|
||||||
mdbData.mv_data = nil
|
|
||||||
mdbData.mv_size = 0
|
|
||||||
|
|
||||||
let result = mdb_cursor_get(self.cursor, &mdbKey, &mdbData, MDB_NEXT)
|
|
||||||
if result == MDB_SUCCESS {
|
|
||||||
let actualKey = ValueBoxKey(length: mdbKey.mv_size)
|
|
||||||
memcpy(actualKey.memory, mdbKey.mv_data, mdbKey.mv_size)
|
|
||||||
|
|
||||||
let value = malloc(mdbData.mv_size)!
|
|
||||||
memcpy(value, mdbData.mv_data, mdbData.mv_size)
|
|
||||||
|
|
||||||
return (actualKey, ReadBuffer(memory: value, length: mdbData.mv_size, freeWhenDone: true))
|
|
||||||
} else if result == MDB_NOTFOUND {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
print("(LmdbValueBox mdb_cursor_get failed with \(result))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class LmdbValueBox: ValueBox {
|
|
||||||
private var env: OpaquePointer? = nil
|
|
||||||
private var tables: [Int32 : LmdbTable] = [:]
|
|
||||||
|
|
||||||
private var sharedTxn: OpaquePointer? = nil
|
|
||||||
|
|
||||||
private var readQueryTime: CFAbsoluteTime = 0.0
|
|
||||||
private var writeQueryTime: CFAbsoluteTime = 0.0
|
|
||||||
private var commitTime: CFAbsoluteTime = 0.0
|
|
||||||
|
|
||||||
public init?(basePath: String) {
|
|
||||||
var result = mdb_env_create(&self.env)
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_env_create failed with \(result))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = basePath + "/lmdb"
|
|
||||||
|
|
||||||
var createDirectory = false
|
|
||||||
var isDirectory: ObjCBool = false as ObjCBool
|
|
||||||
if FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) {
|
|
||||||
if !isDirectory.boolValue {
|
|
||||||
do {
|
|
||||||
try FileManager.default.removeItem(atPath: path)
|
|
||||||
} catch _ { }
|
|
||||||
createDirectory = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
createDirectory = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if createDirectory {
|
|
||||||
do {
|
|
||||||
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
} catch _ { }
|
|
||||||
}
|
|
||||||
|
|
||||||
mdb_env_set_mapsize(self.env, 500 * 1024 * 1024);
|
|
||||||
mdb_env_set_maxdbs(self.env, 64)
|
|
||||||
|
|
||||||
path.withCString { string in
|
|
||||||
result = mdb_env_open(self.env, string, UInt32(MDB_NOSYNC), 0o664)
|
|
||||||
}
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_env_open failed with \(result))")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var removedReaders: Int32 = 0
|
|
||||||
result = mdb_reader_check(self.env, &removedReaders)
|
|
||||||
|
|
||||||
if removedReaders != 0 {
|
|
||||||
print("(LmdbValueBox removed \(removedReaders) stale readers)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
mdb_env_close(self.env)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createTableWithName(_ name: Int32) -> LmdbTable? {
|
|
||||||
var dbi = MDB_dbi()
|
|
||||||
let result = mdb_dbi_open(self.sharedTxn, "\(name)", UInt32(MDB_CREATE), &dbi)
|
|
||||||
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_dbi_open failed with \(result))")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return LmdbTable(dbi: dbi)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func beginStats() {
|
|
||||||
self.readQueryTime = 0.0
|
|
||||||
self.writeQueryTime = 0.0
|
|
||||||
self.commitTime = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func endStats() {
|
|
||||||
print("(LmdbValueBox stats read: \(self.readQueryTime * 1000.0) ms, write: \(self.writeQueryTime * 1000.0) ms, commit: \(self.commitTime * 1000.0) ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
public func begin() {
|
|
||||||
if self.sharedTxn != nil {
|
|
||||||
print("(LmdbValueBox already in transaction)")
|
|
||||||
} else {
|
|
||||||
let result = mdb_txn_begin(self.env, nil, 0, &sharedTxn)
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox txn_begin failed with \(result))")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func commit() {
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
if self.sharedTxn == nil {
|
|
||||||
print("(LmdbValueBox already no current transaction)")
|
|
||||||
} else {
|
|
||||||
let result = mdb_txn_commit(self.sharedTxn)
|
|
||||||
self.sharedTxn = nil
|
|
||||||
self.commitTime += CFAbsoluteTimeGetCurrent() - startTime
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox txn_commit failed with \(result))")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func range(_ table: Int32, start: ValueBoxKey, end: ValueBoxKey, values: @noescape(ValueBoxKey, ReadBuffer) -> Bool, limit: Int) {
|
|
||||||
if start == end || limit == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var commit = false
|
|
||||||
if self.sharedTxn == nil {
|
|
||||||
self.begin()
|
|
||||||
commit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var nativeTable: LmdbTable?
|
|
||||||
if let existingTable = self.tables[table] {
|
|
||||||
nativeTable = existingTable
|
|
||||||
} else if let createdTable = self.createTableWithName(table) {
|
|
||||||
nativeTable = createdTable
|
|
||||||
self.tables[table] = createdTable
|
|
||||||
}
|
|
||||||
|
|
||||||
if let nativeTable = nativeTable {
|
|
||||||
var startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
var cursorPtr: OpaquePointer? = nil
|
|
||||||
let result = mdb_cursor_open(self.sharedTxn, nativeTable.dbi, &cursorPtr)
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_cursor_open failed with \(result))")
|
|
||||||
} else {
|
|
||||||
let cursor = LmdbCursor(cursor: cursorPtr)
|
|
||||||
|
|
||||||
if start < end {
|
|
||||||
var value = cursor.seekTo(start, forward: true)
|
|
||||||
if value != nil {
|
|
||||||
if value!.0 == start {
|
|
||||||
value = cursor.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
readQueryTime += currentTime - startTime
|
|
||||||
startTime = currentTime
|
|
||||||
|
|
||||||
var count = 0
|
|
||||||
if value != nil && value!.0 < end {
|
|
||||||
count += 1
|
|
||||||
let _ = values(value!.0, value!.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
while value != nil && value!.0 < end && count < limit {
|
|
||||||
startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
value = cursor.next()
|
|
||||||
|
|
||||||
currentTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
readQueryTime += currentTime - startTime
|
|
||||||
startTime = currentTime
|
|
||||||
|
|
||||||
if value != nil && value!.0 < end {
|
|
||||||
count += 1
|
|
||||||
let _ = values(value!.0, value!.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
var value = cursor.seekTo(start, forward: false)
|
|
||||||
if value != nil {
|
|
||||||
if value!.0 == start {
|
|
||||||
value = cursor.previous()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
readQueryTime += currentTime - startTime
|
|
||||||
startTime = currentTime
|
|
||||||
|
|
||||||
var count = 0
|
|
||||||
if value != nil && value!.0 > end {
|
|
||||||
count += 1
|
|
||||||
let _ = values(value!.0, value!.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
while value != nil && value!.0 > end && count < limit {
|
|
||||||
startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
value = cursor.previous()
|
|
||||||
|
|
||||||
currentTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
readQueryTime += currentTime - startTime
|
|
||||||
startTime = currentTime
|
|
||||||
|
|
||||||
if value != nil && value!.0 > end {
|
|
||||||
count += 1
|
|
||||||
let _ = values(value!.0, value!.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mdb_cursor_close(cursorPtr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if commit {
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
self.commit()
|
|
||||||
|
|
||||||
readQueryTime += CFAbsoluteTimeGetCurrent() - startTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func range(_ table: Int32, start: ValueBoxKey, end: ValueBoxKey, keys: @noescape(ValueBoxKey) -> Bool, limit: Int) {
|
|
||||||
self.range(table, start: start, end: end, values: { key, _ in
|
|
||||||
return keys(key)
|
|
||||||
}, limit: limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func get(_ table: Int32, key: ValueBoxKey) -> ReadBuffer? {
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
var commit = false
|
|
||||||
if self.sharedTxn == nil {
|
|
||||||
self.begin()
|
|
||||||
commit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var nativeTable: LmdbTable?
|
|
||||||
if let existingTable = self.tables[table] {
|
|
||||||
nativeTable = existingTable
|
|
||||||
} else if let createdTable = self.createTableWithName(table) {
|
|
||||||
nativeTable = createdTable
|
|
||||||
self.tables[table] = createdTable
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultValue: ReadBuffer?
|
|
||||||
|
|
||||||
if let nativeTable = nativeTable {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
var mdbData = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = key.memory
|
|
||||||
mdbKey.mv_size = key.length
|
|
||||||
|
|
||||||
let result = mdb_get(self.sharedTxn, nativeTable.dbi, &mdbKey, &mdbData)
|
|
||||||
|
|
||||||
if result == MDB_SUCCESS {
|
|
||||||
let value = malloc(mdbData.mv_size)!
|
|
||||||
memcpy(value, mdbData.mv_data, mdbData.mv_size)
|
|
||||||
resultValue = ReadBuffer(memory: value, length: mdbData.mv_size, freeWhenDone: true)
|
|
||||||
} else {
|
|
||||||
if result != MDB_NOTFOUND {
|
|
||||||
print("(LmdbValueBox mdb_get failed with \(result))")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if commit {
|
|
||||||
self.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
readQueryTime += CFAbsoluteTimeGetCurrent() - startTime
|
|
||||||
|
|
||||||
return resultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
public func exists(_ table: Int32, key: ValueBoxKey) -> Bool {
|
|
||||||
return self.get(table, key: key) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
public func set(_ table: Int32, key: ValueBoxKey, value: MemoryBuffer) {
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
var commit = false
|
|
||||||
if self.sharedTxn == nil {
|
|
||||||
self.begin()
|
|
||||||
commit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var nativeTable: LmdbTable?
|
|
||||||
if let existingTable = self.tables[table] {
|
|
||||||
nativeTable = existingTable
|
|
||||||
} else if let createdTable = self.createTableWithName(table) {
|
|
||||||
nativeTable = createdTable
|
|
||||||
self.tables[table] = createdTable
|
|
||||||
}
|
|
||||||
|
|
||||||
if let nativeTable = nativeTable {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
var mdbData = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = key.memory
|
|
||||||
mdbKey.mv_size = key.length
|
|
||||||
mdbData.mv_data = value.memory
|
|
||||||
mdbData.mv_size = value.length
|
|
||||||
|
|
||||||
let result = mdb_put(self.sharedTxn, nativeTable.dbi, &mdbKey, &mdbData, 0)
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_set failed with \(result))")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if commit {
|
|
||||||
self.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
writeQueryTime += CFAbsoluteTimeGetCurrent() - startTime
|
|
||||||
}
|
|
||||||
|
|
||||||
public func remove(_ table: Int32, key: ValueBoxKey) {
|
|
||||||
let startTime = CFAbsoluteTimeGetCurrent()
|
|
||||||
|
|
||||||
var commit = false
|
|
||||||
if self.sharedTxn == nil {
|
|
||||||
self.begin()
|
|
||||||
commit = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var nativeTable: LmdbTable?
|
|
||||||
if let existingTable = self.tables[table] {
|
|
||||||
nativeTable = existingTable
|
|
||||||
} else if let createdTable = self.createTableWithName(table) {
|
|
||||||
nativeTable = createdTable
|
|
||||||
self.tables[table] = createdTable
|
|
||||||
}
|
|
||||||
|
|
||||||
if let nativeTable = nativeTable {
|
|
||||||
var mdbKey = MDB_val()
|
|
||||||
|
|
||||||
mdbKey.mv_data = key.memory
|
|
||||||
mdbKey.mv_size = key.length
|
|
||||||
|
|
||||||
let result = mdb_del(self.sharedTxn, nativeTable.dbi, &mdbKey, nil)
|
|
||||||
if result != MDB_SUCCESS {
|
|
||||||
print("(LmdbValueBox mdb_set failed with \(result))")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if commit {
|
|
||||||
self.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
writeQueryTime += CFAbsoluteTimeGetCurrent() - startTime
|
|
||||||
}
|
|
||||||
|
|
||||||
public func drop() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ import Foundation
|
|||||||
public final class MappedFile {
|
public final class MappedFile {
|
||||||
private var handle: Int32
|
private var handle: Int32
|
||||||
private var currentSize: Int
|
private var currentSize: Int
|
||||||
private var memory: UnsafeMutablePointer<Void>
|
private var memory: UnsafeMutableRawPointer
|
||||||
|
|
||||||
public init(path: String) {
|
public init(path: String) {
|
||||||
self.handle = open(path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
self.handle = open(path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
|
||||||
|
@ -116,7 +116,7 @@ public final class MediaBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.statusQueue.async {
|
self.statusQueue.async {
|
||||||
if let statusContext = self.statusContexts[resource.id] where statusContext.status == nil {
|
if let statusContext = self.statusContexts[resource.id] , statusContext.status == nil {
|
||||||
statusContext.status = status
|
statusContext.status = status
|
||||||
|
|
||||||
for subscriber in statusContext.subscribers.copyItems() {
|
for subscriber in statusContext.subscribers.copyItems() {
|
||||||
@ -499,7 +499,7 @@ public final class MediaBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.statusQueue.async {
|
self.statusQueue.async {
|
||||||
if let statusContext = self.statusContexts[resource.id] where statusContext.status != status {
|
if let statusContext = self.statusContexts[resource.id] , statusContext.status != status {
|
||||||
statusContext.status = status
|
statusContext.status = status
|
||||||
for subscriber in statusContext.subscribers.copyItems() {
|
for subscriber in statusContext.subscribers.copyItems() {
|
||||||
subscriber(status)
|
subscriber(status)
|
||||||
@ -523,7 +523,7 @@ public final class MediaBox {
|
|||||||
|
|
||||||
public func cancelInteractiveResourceFetch(_ resource: MediaResource) {
|
public func cancelInteractiveResourceFetch(_ resource: MediaResource) {
|
||||||
self.dataQueue.async {
|
self.dataQueue.async {
|
||||||
if let dataContext = self.dataContexts[resource.id] where dataContext.fetchDisposable != nil {
|
if let dataContext = self.dataContexts[resource.id] , dataContext.fetchDisposable != nil {
|
||||||
dataContext.fetchDisposable?.dispose()
|
dataContext.fetchDisposable?.dispose()
|
||||||
dataContext.fetchDisposable = nil
|
dataContext.fetchDisposable = nil
|
||||||
|
|
||||||
@ -536,7 +536,7 @@ public final class MediaBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.statusQueue.async {
|
self.statusQueue.async {
|
||||||
if let statusContext = self.statusContexts[resource.id] where statusContext.status != status {
|
if let statusContext = self.statusContexts[resource.id] , statusContext.status != status {
|
||||||
statusContext.status = status
|
statusContext.status = status
|
||||||
for subscriber in statusContext.subscribers.copyItems() {
|
for subscriber in statusContext.subscribers.copyItems() {
|
||||||
subscriber(status)
|
subscriber(status)
|
||||||
|
@ -230,7 +230,7 @@ public func ==(lhs: MessageForwardInfo, rhs: MessageForwardInfo) -> Bool {
|
|||||||
if !lhs.author.isEqual(rhs.author) {
|
if !lhs.author.isEqual(rhs.author) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if let lhsSource = lhs.source, rhsSource = rhs.source {
|
if let lhsSource = lhs.source, let rhsSource = rhs.source {
|
||||||
if !lhsSource.isEqual(rhsSource) {
|
if !lhsSource.isEqual(rhsSource) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public func <(lhs: MessageHistoryHolesViewEntry, rhs: MessageHistoryHolesViewEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class MutableMessageHistoryHolesView {
|
final class MutableMessageHistoryHolesView {
|
||||||
private var entries: [PeerId: Set<MessageHistoryHolesViewEntry>] = [:]
|
fileprivate var entries: [PeerId: Set<MessageHistoryHolesViewEntry>] = [:]
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ final class MessageHistoryIndexTable: Table {
|
|||||||
|
|
||||||
let adjacent = self.adjacentItems(id)
|
let adjacent = self.adjacentItems(id)
|
||||||
|
|
||||||
if let lowerItem = adjacent.lower, upperItem = adjacent.upper {
|
if let lowerItem = adjacent.lower, let upperItem = adjacent.upper {
|
||||||
switch lowerItem {
|
switch lowerItem {
|
||||||
case let .Message(lowerMessage):
|
case let .Message(lowerMessage):
|
||||||
switch upperItem {
|
switch upperItem {
|
||||||
@ -471,7 +471,7 @@ final class MessageHistoryIndexTable: Table {
|
|||||||
self.justRemove(upperHole.maxIndex, operations: &operations)
|
self.justRemove(upperHole.maxIndex, operations: &operations)
|
||||||
}
|
}
|
||||||
} else if fillType.direction == .LowerToUpper {
|
} else if fillType.direction == .LowerToUpper {
|
||||||
if let maxMessageInRange = maxMessageInRange where maxMessageInRange.id.id != Int32.max && maxMessageInRange.id.id + 1 <= upperHole.maxIndex.id.id {
|
if let maxMessageInRange = maxMessageInRange , maxMessageInRange.id.id != Int32.max && maxMessageInRange.id.id + 1 <= upperHole.maxIndex.id.id {
|
||||||
let stableId: UInt32
|
let stableId: UInt32
|
||||||
let tags: UInt32 = upperHole.tags
|
let tags: UInt32 = upperHole.tags
|
||||||
if removedHole {
|
if removedHole {
|
||||||
@ -482,7 +482,7 @@ final class MessageHistoryIndexTable: Table {
|
|||||||
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: upperHole.maxIndex, min: maxMessageInRange.id.id + 1, tags: tags), operations: &operations)
|
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: upperHole.maxIndex, min: maxMessageInRange.id.id + 1, tags: tags), operations: &operations)
|
||||||
}
|
}
|
||||||
} else if fillType.direction == .UpperToLower {
|
} else if fillType.direction == .UpperToLower {
|
||||||
if let minMessageInRange = minMessageInRange where minMessageInRange.id.id - 1 >= upperHole.min {
|
if let minMessageInRange = minMessageInRange , minMessageInRange.id.id - 1 >= upperHole.min {
|
||||||
let stableId: UInt32
|
let stableId: UInt32
|
||||||
let tags: UInt32 = upperHole.tags
|
let tags: UInt32 = upperHole.tags
|
||||||
if removedHole {
|
if removedHole {
|
||||||
@ -498,14 +498,14 @@ final class MessageHistoryIndexTable: Table {
|
|||||||
removedHole = true
|
removedHole = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let minMessageInRange = minMessageInRange where minMessageInRange.id.id - 1 >= upperHole.min {
|
if let minMessageInRange = minMessageInRange , minMessageInRange.id.id - 1 >= upperHole.min {
|
||||||
let stableId: UInt32 = upperHole.stableId
|
let stableId: UInt32 = upperHole.stableId
|
||||||
let tags: UInt32 = upperHole.tags
|
let tags: UInt32 = upperHole.tags
|
||||||
|
|
||||||
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: MessageIndex(id: MessageId(peerId: id.peerId, namespace: id.namespace, id: minMessageInRange.id.id - 1), timestamp: minMessageInRange.timestamp), min: upperHole.min, tags: tags), operations: &operations)
|
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: MessageIndex(id: MessageId(peerId: id.peerId, namespace: id.namespace, id: minMessageInRange.id.id - 1), timestamp: minMessageInRange.timestamp), min: upperHole.min, tags: tags), operations: &operations)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let maxMessageInRange = maxMessageInRange where maxMessageInRange.id.id != Int32.max && maxMessageInRange.id.id + 1 <= upperHole.maxIndex.id.id {
|
if let maxMessageInRange = maxMessageInRange , maxMessageInRange.id.id != Int32.max && maxMessageInRange.id.id + 1 <= upperHole.maxIndex.id.id {
|
||||||
let stableId: UInt32 = self.metadataTable.getNextStableMessageIndexId()
|
let stableId: UInt32 = self.metadataTable.getNextStableMessageIndexId()
|
||||||
let tags: UInt32 = upperHole.tags
|
let tags: UInt32 = upperHole.tags
|
||||||
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: upperHole.maxIndex, min: maxMessageInRange.id.id + 1, tags: tags), operations: &operations)
|
self.justInsertHole(MessageHistoryHole(stableId: stableId, maxIndex: upperHole.maxIndex, min: maxMessageInRange.id.id + 1, tags: tags), operations: &operations)
|
||||||
@ -648,7 +648,7 @@ final class MessageHistoryIndexTable: Table {
|
|||||||
value.read(&flags, offset: 0, length: 1)
|
value.read(&flags, offset: 0, length: 1)
|
||||||
if (flags & HistoryEntryTypeMask) == HistoryEntryTypeHole {
|
if (flags & HistoryEntryTypeMask) == HistoryEntryTypeHole {
|
||||||
value.reset()
|
value.reset()
|
||||||
if case let .Hole(hole) = readHistoryIndexEntry(peerId, namespace: namespace, key: key, value: value) where hole.min <= maxId && hole.maxIndex.id.id >= maxId {
|
if case let .Hole(hole) = readHistoryIndexEntry(peerId, namespace: namespace, key: key, value: value) , hole.min <= maxId && hole.maxIndex.id.id >= maxId {
|
||||||
holes = true
|
holes = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ final class MessageHistoryMetadataTable: Table {
|
|||||||
let sharedBuffer = WriteBuffer()
|
let sharedBuffer = WriteBuffer()
|
||||||
for (peerId, namespaces) in self.updatedPeerNextMessageIdByNamespace {
|
for (peerId, namespaces) in self.updatedPeerNextMessageIdByNamespace {
|
||||||
for namespace in namespaces {
|
for namespace in namespaces {
|
||||||
if let messageIdByNamespace = self.peerNextMessageIdByNamespace[peerId], maxId = messageIdByNamespace[namespace] {
|
if let messageIdByNamespace = self.peerNextMessageIdByNamespace[peerId], let maxId = messageIdByNamespace[namespace] {
|
||||||
sharedBuffer.reset()
|
sharedBuffer.reset()
|
||||||
var mutableMaxId = maxId
|
var mutableMaxId = maxId
|
||||||
sharedBuffer.write(&mutableMaxId, offset: 0, length: 4)
|
sharedBuffer.write(&mutableMaxId, offset: 0, length: 4)
|
||||||
|
@ -200,7 +200,7 @@ final class MessageHistoryReadStateTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyIncomingMaxReadId(_ messageId: MessageId, incomingStatsInRange: (MessageId.Id, MessageId.Id) -> (count: Int, holes: Bool), topMessageId: MessageId.Id?) -> (CombinedPeerReadState?, Bool) {
|
func applyIncomingMaxReadId(_ messageId: MessageId, incomingStatsInRange: (MessageId.Id, MessageId.Id) -> (count: Int, holes: Bool), topMessageId: MessageId.Id?) -> (CombinedPeerReadState?, Bool) {
|
||||||
if let states = self.get(messageId.peerId), state = states.namespaces[messageId.namespace] {
|
if let states = self.get(messageId.peerId), let state = states.namespaces[messageId.namespace] {
|
||||||
if traceReadStates {
|
if traceReadStates {
|
||||||
print("[ReadStateTable] applyMaxReadId peerId: \(messageId.peerId), maxReadId: \(messageId.id) (before: \(states.namespaces))")
|
print("[ReadStateTable] applyMaxReadId peerId: \(messageId.peerId), maxReadId: \(messageId.id) (before: \(states.namespaces))")
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ final class MessageHistoryReadStateTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyOutgoingMaxReadId(_ messageId: MessageId) -> (CombinedPeerReadState?, Bool) {
|
func applyOutgoingMaxReadId(_ messageId: MessageId) -> (CombinedPeerReadState?, Bool) {
|
||||||
if let states = self.get(messageId.peerId), state = states.namespaces[messageId.namespace] {
|
if let states = self.get(messageId.peerId), let state = states.namespaces[messageId.namespace] {
|
||||||
if state.maxOutgoingReadId < messageId.id {
|
if state.maxOutgoingReadId < messageId.id {
|
||||||
states.namespaces[messageId.namespace] = PeerReadState(maxIncomingReadId: state.maxIncomingReadId, maxOutgoingReadId: state.maxOutgoingReadId, maxKnownId: state.maxKnownId, count: state.count)
|
states.namespaces[messageId.namespace] = PeerReadState(maxIncomingReadId: state.maxIncomingReadId, maxOutgoingReadId: state.maxOutgoingReadId, maxKnownId: state.maxKnownId, count: state.count)
|
||||||
self.updatedPeerIds.insert(messageId.peerId)
|
self.updatedPeerIds.insert(messageId.peerId)
|
||||||
@ -262,7 +262,7 @@ final class MessageHistoryReadStateTable: Table {
|
|||||||
override func beforeCommit() {
|
override func beforeCommit() {
|
||||||
let sharedBuffer = WriteBuffer()
|
let sharedBuffer = WriteBuffer()
|
||||||
for id in self.updatedPeerIds {
|
for id in self.updatedPeerIds {
|
||||||
if let wrappedStates = self.cachedPeerReadStates[id], states = wrappedStates {
|
if let wrappedStates = self.cachedPeerReadStates[id], let states = wrappedStates {
|
||||||
sharedBuffer.reset()
|
sharedBuffer.reset()
|
||||||
var count: Int32 = Int32(states.namespaces.count)
|
var count: Int32 = Int32(states.namespaces.count)
|
||||||
sharedBuffer.write(&count, offset: 0, length: 4)
|
sharedBuffer.write(&count, offset: 0, length: 4)
|
||||||
|
@ -610,7 +610,7 @@ final class MessageHistoryTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func embeddedMediaForIndex(_ index: MessageIndex, id: MediaId) -> Media? {
|
func embeddedMediaForIndex(_ index: MessageIndex, id: MediaId) -> Media? {
|
||||||
if let message = self.getMessage(index) where message.embeddedMediaData.length > 4 {
|
if let message = self.getMessage(index), message.embeddedMediaData.length > 4 {
|
||||||
var embeddedMediaCount: Int32 = 0
|
var embeddedMediaCount: Int32 = 0
|
||||||
message.embeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
message.embeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
||||||
|
|
||||||
@ -619,7 +619,7 @@ final class MessageHistoryTable: Table {
|
|||||||
message.embeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
message.embeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
||||||
if let readMedia = Decoder(buffer: MemoryBuffer(memory: message.embeddedMediaData.memory + message.embeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
if let readMedia = Decoder(buffer: MemoryBuffer(memory: message.embeddedMediaData.memory + message.embeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
||||||
|
|
||||||
if let readMediaId = readMedia.id where readMediaId == id {
|
if let readMediaId = readMedia.id, readMediaId == id {
|
||||||
return readMedia
|
return readMedia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,7 +880,7 @@ final class MessageHistoryTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unembedMedia(_ index: MessageIndex, id: MediaId) -> Media? {
|
func unembedMedia(_ index: MessageIndex, id: MediaId) -> Media? {
|
||||||
if let message = self.getMessage(index) where message.embeddedMediaData.length > 4 {
|
if let message = self.getMessage(index), message.embeddedMediaData.length > 4 {
|
||||||
var embeddedMediaCount: Int32 = 0
|
var embeddedMediaCount: Int32 = 0
|
||||||
message.embeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
message.embeddedMediaData.read(&embeddedMediaCount, offset: 0, length: 4)
|
||||||
|
|
||||||
@ -897,14 +897,14 @@ final class MessageHistoryTable: Table {
|
|||||||
message.embeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
message.embeddedMediaData.read(&mediaLength, offset: 0, length: 4)
|
||||||
if let media = Decoder(buffer: MemoryBuffer(memory: message.embeddedMediaData.memory + message.embeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
if let media = Decoder(buffer: MemoryBuffer(memory: message.embeddedMediaData.memory + message.embeddedMediaData.offset, capacity: Int(mediaLength), length: Int(mediaLength), freeWhenDone: false)).decodeRootObject() as? Media {
|
||||||
|
|
||||||
if let mediaId = media.id where mediaId == id {
|
if let mediaId = media.id, mediaId == id {
|
||||||
copyMedia = false
|
copyMedia = false
|
||||||
extractedMedia = media
|
extractedMedia = media
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if copyMedia {
|
if copyMedia {
|
||||||
updatedEmbeddedMediaBuffer.write(message.embeddedMediaData.memory + mediaOffset, offset: 0, length: message.embeddedMediaData.offset - mediaOffset)
|
updatedEmbeddedMediaBuffer.write(message.embeddedMediaData.memory.advanced(by: mediaOffset), offset: 0, length: message.embeddedMediaData.offset - mediaOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,7 +1055,7 @@ final class MessageHistoryTable: Table {
|
|||||||
|
|
||||||
var textLength: Int32 = 0
|
var textLength: Int32 = 0
|
||||||
value.read(&textLength, offset: 0, length: 4)
|
value.read(&textLength, offset: 0, length: 4)
|
||||||
let text = String(data: Data(bytes: UnsafeMutablePointer<UInt8>(value.memory).advanced(by: value.offset), count: Int(textLength)), encoding: .utf8) ?? ""
|
let text = String(data: Data(bytes: value.memory.assumingMemoryBound(to: UInt8.self).advanced(by: value.offset), count: Int(textLength)), encoding: .utf8) ?? ""
|
||||||
//let text = NSString(bytes: value.memory + value.offset, length: Int(textLength), encoding: NSUTF8StringEncoding) ?? ""
|
//let text = NSString(bytes: value.memory + value.offset, length: Int(textLength), encoding: NSUTF8StringEncoding) ?? ""
|
||||||
value.skip(Int(textLength))
|
value.skip(Int(textLength))
|
||||||
|
|
||||||
@ -1151,7 +1151,7 @@ final class MessageHistoryTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var forwardInfo: MessageForwardInfo?
|
var forwardInfo: MessageForwardInfo?
|
||||||
if let internalForwardInfo = message.forwardInfo, forwardAuthor = peerTable.get(internalForwardInfo.authorId) {
|
if let internalForwardInfo = message.forwardInfo, let forwardAuthor = peerTable.get(internalForwardInfo.authorId) {
|
||||||
var source: Peer?
|
var source: Peer?
|
||||||
|
|
||||||
if let sourceId = internalForwardInfo.sourceId {
|
if let sourceId = internalForwardInfo.sourceId {
|
||||||
@ -1345,7 +1345,7 @@ final class MessageHistoryTable: Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maxReadIndex(_ peerId: PeerId) -> MessageHistoryAnchorIndex? {
|
func maxReadIndex(_ peerId: PeerId) -> MessageHistoryAnchorIndex? {
|
||||||
if let combinedState = self.readStateTable.getCombinedState(peerId), state = combinedState.states.first where state.1.count != 0 {
|
if let combinedState = self.readStateTable.getCombinedState(peerId), let state = combinedState.states.first , state.1.count != 0 {
|
||||||
return self.anchorIndex(MessageId(peerId: peerId, namespace: state.0, id: state.1.maxIncomingReadId))
|
return self.anchorIndex(MessageId(peerId: peerId, namespace: state.0, id: state.1.maxIncomingReadId))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -1353,10 +1353,10 @@ final class MessageHistoryTable: Table {
|
|||||||
|
|
||||||
func anchorIndex(_ messageId: MessageId) -> MessageHistoryAnchorIndex? {
|
func anchorIndex(_ messageId: MessageId) -> MessageHistoryAnchorIndex? {
|
||||||
let (lower, upper) = self.messageHistoryIndexTable.adjacentItems(messageId, bindUpper: false)
|
let (lower, upper) = self.messageHistoryIndexTable.adjacentItems(messageId, bindUpper: false)
|
||||||
if let lower = lower, case let .Hole(hole) = lower where messageId.id >= hole.min && messageId.id <= hole.maxIndex.id.id {
|
if let lower = lower, case let .Hole(hole) = lower, messageId.id >= hole.min && messageId.id <= hole.maxIndex.id.id {
|
||||||
return MessageHistoryAnchorIndex(index: MessageIndex(id: messageId, timestamp: lower.index.timestamp), exact: false)
|
return MessageHistoryAnchorIndex(index: MessageIndex(id: messageId, timestamp: lower.index.timestamp), exact: false)
|
||||||
}
|
}
|
||||||
if let upper = upper, case let .Hole(hole) = upper where messageId.id >= hole.min && messageId.id <= hole.maxIndex.id.id {
|
if let upper = upper, case let .Hole(hole) = upper, messageId.id >= hole.min && messageId.id <= hole.maxIndex.id.id {
|
||||||
return MessageHistoryAnchorIndex(index: MessageIndex(id: messageId, timestamp: upper.index.timestamp), exact: false)
|
return MessageHistoryAnchorIndex(index: MessageIndex(id: messageId, timestamp: upper.index.timestamp), exact: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +126,12 @@ final class MutableMessageHistoryViewReplayContext {
|
|||||||
final class MutableMessageHistoryView {
|
final class MutableMessageHistoryView {
|
||||||
private(set) var id: MessageHistoryViewId
|
private(set) var id: MessageHistoryViewId
|
||||||
let tagMask: MessageTags?
|
let tagMask: MessageTags?
|
||||||
private var anchorIndex: MessageHistoryAnchorIndex
|
fileprivate var anchorIndex: MessageHistoryAnchorIndex
|
||||||
private let combinedReadState: CombinedPeerReadState?
|
fileprivate let combinedReadState: CombinedPeerReadState?
|
||||||
private var earlier: MutableMessageHistoryEntry?
|
fileprivate var earlier: MutableMessageHistoryEntry?
|
||||||
private var later: MutableMessageHistoryEntry?
|
fileprivate var later: MutableMessageHistoryEntry?
|
||||||
private var entries: [MutableMessageHistoryEntry]
|
fileprivate var entries: [MutableMessageHistoryEntry]
|
||||||
private let fillCount: Int
|
fileprivate let fillCount: Int
|
||||||
|
|
||||||
init(id: MessageHistoryViewId, anchorIndex: MessageHistoryAnchorIndex, combinedReadState: CombinedPeerReadState?, earlier: MutableMessageHistoryEntry?, entries: [MutableMessageHistoryEntry], later: MutableMessageHistoryEntry?, tagMask: MessageTags?, count: Int) {
|
init(id: MessageHistoryViewId, anchorIndex: MessageHistoryAnchorIndex, combinedReadState: CombinedPeerReadState?, earlier: MutableMessageHistoryEntry?, entries: [MutableMessageHistoryEntry], later: MutableMessageHistoryEntry?, tagMask: MessageTags?, count: Int) {
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -166,7 +166,7 @@ final class MutableMessageHistoryView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let minIndex = minIndex, maxIndex = maxIndex {
|
if let minIndex = minIndex, let maxIndex = maxIndex {
|
||||||
var minClipIndex = minIndex
|
var minClipIndex = minIndex
|
||||||
var maxClipIndex = maxIndex
|
var maxClipIndex = maxIndex
|
||||||
|
|
||||||
@ -222,13 +222,15 @@ final class MutableMessageHistoryView {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshDueToExternalTransaction(fetchAroundHistoryEntries: (index: MessageIndex, count: Int, tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?)) -> Bool {
|
func refreshDueToExternalTransaction(fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?)) -> Bool {
|
||||||
var index = MessageIndex.absoluteUpperBound()
|
var index = MessageIndex.upperBound(peerId: self.anchorIndex.index.id.peerId)
|
||||||
if !self.entries.isEmpty {
|
if !self.entries.isEmpty {
|
||||||
index = self.entries[self.entries.count / 2].index
|
if let _ = self.later {
|
||||||
|
index = self.entries[self.entries.count / 2].index
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (entries, earlier, later) = fetchAroundHistoryEntries(index: index, count: max(self.fillCount, self.entries.count), tagMask: self.tagMask)
|
let (entries, earlier, later) = fetchAroundHistoryEntries(index, max(self.fillCount, self.entries.count), self.tagMask)
|
||||||
|
|
||||||
self.entries = entries
|
self.entries = entries
|
||||||
self.earlier = earlier
|
self.earlier = earlier
|
||||||
@ -268,7 +270,7 @@ final class MutableMessageHistoryView {
|
|||||||
//self.combinedReadState = combinedReadState
|
//self.combinedReadState = combinedReadState
|
||||||
case let .UpdateEmbeddedMedia(index, embeddedMediaData):
|
case let .UpdateEmbeddedMedia(index, embeddedMediaData):
|
||||||
for i in 0 ..< self.entries.count {
|
for i in 0 ..< self.entries.count {
|
||||||
if case let .IntermediateMessageEntry(message, _) = self.entries[i] where MessageIndex(message) == index {
|
if case let .IntermediateMessageEntry(message, _) = self.entries[i] , MessageIndex(message) == index {
|
||||||
self.entries[i] = .IntermediateMessageEntry(IntermediateMessage(stableId: message.stableId, id: message.id, timestamp: message.timestamp, flags: message.flags, tags: message.tags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: embeddedMediaData, referencedMedia: message.referencedMedia), nil)
|
self.entries[i] = .IntermediateMessageEntry(IntermediateMessage(stableId: message.stableId, id: message.id, timestamp: message.timestamp, flags: message.flags, tags: message.tags, forwardInfo: message.forwardInfo, authorId: message.authorId, text: message.text, attributesData: message.attributesData, embeddedMediaData: embeddedMediaData, referencedMedia: message.referencedMedia), nil)
|
||||||
hasChanges = true
|
hasChanges = true
|
||||||
break
|
break
|
||||||
@ -283,7 +285,7 @@ final class MutableMessageHistoryView {
|
|||||||
case let .MessageEntry(message, _):
|
case let .MessageEntry(message, _):
|
||||||
var rebuild = false
|
var rebuild = false
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if let mediaId = media.id, _ = updatedMedia[mediaId] {
|
if let mediaId = media.id, let _ = updatedMedia[mediaId] {
|
||||||
rebuild = true
|
rebuild = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -292,7 +294,7 @@ final class MutableMessageHistoryView {
|
|||||||
if rebuild {
|
if rebuild {
|
||||||
var messageMedia: [Media] = []
|
var messageMedia: [Media] = []
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if let mediaId = media.id, updated = updatedMedia[mediaId] {
|
if let mediaId = media.id, let updated = updatedMedia[mediaId] {
|
||||||
if let updated = updated {
|
if let updated = updated {
|
||||||
messageMedia.append(updated)
|
messageMedia.append(updated)
|
||||||
}
|
}
|
||||||
@ -307,7 +309,7 @@ final class MutableMessageHistoryView {
|
|||||||
case let .IntermediateMessageEntry(message, _):
|
case let .IntermediateMessageEntry(message, _):
|
||||||
var rebuild = false
|
var rebuild = false
|
||||||
for mediaId in message.referencedMedia {
|
for mediaId in message.referencedMedia {
|
||||||
if let media = updatedMedia[mediaId] where media?.id != mediaId {
|
if let media = updatedMedia[mediaId] , media?.id != mediaId {
|
||||||
rebuild = true
|
rebuild = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -315,7 +317,7 @@ final class MutableMessageHistoryView {
|
|||||||
if rebuild {
|
if rebuild {
|
||||||
var referencedMedia: [MediaId] = []
|
var referencedMedia: [MediaId] = []
|
||||||
for mediaId in message.referencedMedia {
|
for mediaId in message.referencedMedia {
|
||||||
if let media = updatedMedia[mediaId] where media?.id != mediaId {
|
if let media = updatedMedia[mediaId] , media?.id != mediaId {
|
||||||
if let id = media?.id {
|
if let id = media?.id {
|
||||||
referencedMedia.append(id)
|
referencedMedia.append(id)
|
||||||
}
|
}
|
||||||
@ -381,12 +383,12 @@ final class MutableMessageHistoryView {
|
|||||||
|
|
||||||
private func remove(_ indices: Set<MessageIndex>, context: MutableMessageHistoryViewReplayContext) -> Bool {
|
private func remove(_ indices: Set<MessageIndex>, context: MutableMessageHistoryViewReplayContext) -> Bool {
|
||||||
var hasChanges = false
|
var hasChanges = false
|
||||||
if let earlier = self.earlier where indices.contains(earlier.index) {
|
if let earlier = self.earlier , indices.contains(earlier.index) {
|
||||||
context.invalidEarlier = true
|
context.invalidEarlier = true
|
||||||
hasChanges = true
|
hasChanges = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let later = self.later where indices.contains(later.index) {
|
if let later = self.later , indices.contains(later.index) {
|
||||||
context.invalidLater = true
|
context.invalidLater = true
|
||||||
hasChanges = true
|
hasChanges = true
|
||||||
}
|
}
|
||||||
@ -571,7 +573,7 @@ public final class MessageHistoryView {
|
|||||||
|
|
||||||
self.combinedReadState = mutableView.combinedReadState
|
self.combinedReadState = mutableView.combinedReadState
|
||||||
|
|
||||||
if let combinedReadState = mutableView.combinedReadState where combinedReadState.count != 0 {
|
if let combinedReadState = mutableView.combinedReadState , combinedReadState.count != 0 {
|
||||||
var maxIndex: MessageIndex?
|
var maxIndex: MessageIndex?
|
||||||
for (namespace, state) in combinedReadState.states {
|
for (namespace, state) in combinedReadState.states {
|
||||||
var maxNamespaceIndex: MessageIndex?
|
var maxNamespaceIndex: MessageIndex?
|
||||||
@ -593,16 +595,16 @@ public final class MessageHistoryView {
|
|||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let _ = maxNamespaceIndex where index + 1 < entries.count {
|
if let _ = maxNamespaceIndex , index + 1 < entries.count {
|
||||||
for i in index + 1 ..< entries.count {
|
for i in index + 1 ..< entries.count {
|
||||||
if case let .MessageEntry(message, _) = entries[i] where !message.flags.contains(.Incoming) {
|
if case let .MessageEntry(message, _) = entries[i] , !message.flags.contains(.Incoming) {
|
||||||
maxNamespaceIndex = MessageIndex(message)
|
maxNamespaceIndex = MessageIndex(message)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let maxNamespaceIndex = maxNamespaceIndex where maxIndex == nil || maxIndex! < maxNamespaceIndex {
|
if let maxNamespaceIndex = maxNamespaceIndex , maxIndex == nil || maxIndex! < maxNamespaceIndex {
|
||||||
maxIndex = maxNamespaceIndex
|
maxIndex = maxNamespaceIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ final class PeerChatStateTable: Table {
|
|||||||
if let state = self.cachedPeerChatStates[id] {
|
if let state = self.cachedPeerChatStates[id] {
|
||||||
return state
|
return state
|
||||||
} else {
|
} else {
|
||||||
if let value = self.valueBox.get(self.tableId, key: self.key(id)), state = Decoder(buffer: value).decodeRootObject() {
|
if let value = self.valueBox.get(self.tableId, key: self.key(id)), let state = Decoder(buffer: value).decodeRootObject() {
|
||||||
self.cachedPeerChatStates[id] = state
|
self.cachedPeerChatStates[id] = state
|
||||||
return state
|
return state
|
||||||
} else {
|
} else {
|
||||||
@ -38,7 +38,7 @@ final class PeerChatStateTable: Table {
|
|||||||
override func beforeCommit() {
|
override func beforeCommit() {
|
||||||
let sharedEncoder = Encoder()
|
let sharedEncoder = Encoder()
|
||||||
for id in self.updatedPeerIds {
|
for id in self.updatedPeerIds {
|
||||||
if let wrappedState = self.cachedPeerChatStates[id], state = wrappedState {
|
if let wrappedState = self.cachedPeerChatStates[id], let state = wrappedState {
|
||||||
sharedEncoder.reset()
|
sharedEncoder.reset()
|
||||||
sharedEncoder.encodeRootObject(state)
|
sharedEncoder.encodeRootObject(state)
|
||||||
self.valueBox.set(self.tableId, key: self.key(id), value: sharedEncoder.readBufferNoCopy())
|
self.valueBox.set(self.tableId, key: self.key(id), value: sharedEncoder.readBufferNoCopy())
|
||||||
|
@ -14,7 +14,7 @@ public protocol PeerChatState: Coding {
|
|||||||
public final class Modifier {
|
public final class Modifier {
|
||||||
private weak var postbox: Postbox?
|
private weak var postbox: Postbox?
|
||||||
|
|
||||||
private init(postbox: Postbox) {
|
fileprivate init(postbox: Postbox) {
|
||||||
self.postbox = postbox
|
self.postbox = postbox
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,11 +130,11 @@ public final class Modifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PipeNotifier: NSObject {
|
fileprivate class PipeNotifier: NSObject {
|
||||||
let notifier: RLMNotifier
|
let notifier: RLMNotifier
|
||||||
let thread: Thread
|
let thread: Thread
|
||||||
|
|
||||||
private init(basePath: String, notify: () -> Void) {
|
fileprivate init(basePath: String, notify: @escaping () -> Void) {
|
||||||
self.notifier = RLMNotifier(basePath: basePath, notify: notify)
|
self.notifier = RLMNotifier(basePath: basePath, notify: notify)
|
||||||
self.thread = Thread(target: PipeNotifier.self, selector: #selector(PipeNotifier.threadEntry(_:)), object: self.notifier)
|
self.thread = Thread(target: PipeNotifier.self, selector: #selector(PipeNotifier.threadEntry(_:)), object: self.notifier)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
@ -304,7 +304,7 @@ public final class Postbox {
|
|||||||
self.metadataTable = MetadataTable(valueBox: self.valueBox, tableId: 0)
|
self.metadataTable = MetadataTable(valueBox: self.valueBox, tableId: 0)
|
||||||
|
|
||||||
let userVersion: Int32? = self.metadataTable.userVersion()
|
let userVersion: Int32? = self.metadataTable.userVersion()
|
||||||
let currentUserVersion: Int32 = 6
|
let currentUserVersion: Int32 = 7
|
||||||
|
|
||||||
if userVersion != currentUserVersion {
|
if userVersion != currentUserVersion {
|
||||||
self.valueBox.drop()
|
self.valueBox.drop()
|
||||||
@ -365,17 +365,15 @@ public final class Postbox {
|
|||||||
|
|
||||||
private var cachedState: Coding?
|
private var cachedState: Coding?
|
||||||
|
|
||||||
private func setState(_ state: Coding) {
|
fileprivate func setState(_ state: Coding) {
|
||||||
self.modify({ modifier -> Void in
|
self.cachedState = state
|
||||||
self.cachedState = state
|
|
||||||
|
self.metadataTable.setState(state)
|
||||||
self.metadataTable.setState(state)
|
|
||||||
|
self.statePipe.putNext(state)
|
||||||
self.statePipe.putNext(state)
|
|
||||||
}).start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getState() -> Coding? {
|
fileprivate func getState() -> Coding? {
|
||||||
if let cachedState = self.cachedState {
|
if let cachedState = self.cachedState {
|
||||||
return cachedState
|
return cachedState
|
||||||
} else {
|
} else {
|
||||||
@ -388,6 +386,7 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated: 1.0)
|
||||||
public func state() -> Signal<Coding?, NoError> {
|
public func state() -> Signal<Coding?, NoError> {
|
||||||
return self.modify { modifier -> Signal<Coding?, NoError> in
|
return self.modify { modifier -> Signal<Coding?, NoError> in
|
||||||
return Signal<Coding?, NoError>.single(self.getState())
|
return Signal<Coding?, NoError>.single(self.getState())
|
||||||
@ -407,15 +406,15 @@ public final class Postbox {
|
|||||||
self.keychainTable.remove(key)
|
self.keychainTable.remove(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addMessages(_ messages: [StoreMessage], location: AddMessagesLocation) {
|
fileprivate func addMessages(_ messages: [StoreMessage], location: AddMessagesLocation) {
|
||||||
self.messageHistoryTable.addMessages(messages, location: location, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.addMessages(messages, location: location, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addHole(_ id: MessageId) {
|
fileprivate func addHole(_ id: MessageId) {
|
||||||
self.messageHistoryTable.addHoles([id], operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.addHoles([id], operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fillHole(_ hole: MessageHistoryHole, fillType: HoleFill, tagMask: MessageTags?, messages: [StoreMessage]) {
|
fileprivate func fillHole(_ hole: MessageHistoryHole, fillType: HoleFill, tagMask: MessageTags?, messages: [StoreMessage]) {
|
||||||
var operationsByPeerId: [PeerId: [MessageHistoryOperation]] = [:]
|
var operationsByPeerId: [PeerId: [MessageHistoryOperation]] = [:]
|
||||||
self.messageHistoryTable.fillHole(hole.id, fillType: fillType, tagMask: tagMask, messages: messages, operationsByPeerId: &operationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.fillHole(hole.id, fillType: fillType, tagMask: tagMask, messages: messages, operationsByPeerId: &operationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
for (peerId, operations) in operationsByPeerId {
|
for (peerId, operations) in operationsByPeerId {
|
||||||
@ -455,31 +454,31 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func replaceChatListHole(_ index: MessageIndex, hole: ChatListHole?) {
|
fileprivate func replaceChatListHole(_ index: MessageIndex, hole: ChatListHole?) {
|
||||||
self.currentReplaceChatListHoles.append((index, hole))
|
self.currentReplaceChatListHoles.append((index, hole))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteMessages(_ messageIds: [MessageId]) {
|
fileprivate func deleteMessages(_ messageIds: [MessageId]) {
|
||||||
self.messageHistoryTable.removeMessages(messageIds, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.removeMessages(messageIds, operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func resetIncomingReadStates(_ states: [PeerId: [MessageId.Namespace: PeerReadState]]) {
|
fileprivate func resetIncomingReadStates(_ states: [PeerId: [MessageId.Namespace: PeerReadState]]) {
|
||||||
self.messageHistoryTable.resetIncomingReadStates(states, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.resetIncomingReadStates(states, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func confirmSynchronizedIncomingReadState(_ peerId: PeerId) {
|
fileprivate func confirmSynchronizedIncomingReadState(_ peerId: PeerId) {
|
||||||
self.synchronizeReadStateTable.set(peerId, operation: nil, operations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.synchronizeReadStateTable.set(peerId, operation: nil, operations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyIncomingReadMaxId(_ messageId: MessageId) {
|
fileprivate func applyIncomingReadMaxId(_ messageId: MessageId) {
|
||||||
self.messageHistoryTable.applyIncomingReadMaxId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.applyIncomingReadMaxId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyOutgoingReadMaxId(_ messageId: MessageId) {
|
fileprivate func applyOutgoingReadMaxId(_ messageId: MessageId) {
|
||||||
self.messageHistoryTable.applyOutgoingReadMaxId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.applyOutgoingReadMaxId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyInteractiveReadMaxId(_ messageId: MessageId) {
|
fileprivate func applyInteractiveReadMaxId(_ messageId: MessageId) {
|
||||||
self.messageHistoryTable.applyInteractiveMaxReadId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.applyInteractiveMaxReadId(messageId, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +647,7 @@ public final class Postbox {
|
|||||||
return self.messageHistoryTable.anchorIndex(id)
|
return self.messageHistoryTable.anchorIndex(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func renderIntermediateMessage(_ message: IntermediateMessage) -> Message {
|
fileprivate func renderIntermediateMessage(_ message: IntermediateMessage) -> Message {
|
||||||
return self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable)
|
return self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +707,7 @@ public final class Postbox {
|
|||||||
return (updatedTransactionState, updatedMasterClientId)
|
return (updatedTransactionState, updatedMasterClientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func messageIdsForGlobalIds(_ ids: [Int32]) -> [MessageId] {
|
fileprivate func messageIdsForGlobalIds(_ ids: [Int32]) -> [MessageId] {
|
||||||
var result: [MessageId] = []
|
var result: [MessageId] = []
|
||||||
for globalId in ids {
|
for globalId in ids {
|
||||||
if let id = self.globalMessageIdsTable.get(globalId) {
|
if let id = self.globalMessageIdsTable.get(globalId) {
|
||||||
@ -718,7 +717,7 @@ public final class Postbox {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updatePeers(_ peers: [Peer], update: (Peer, Peer) -> Peer?) {
|
fileprivate func updatePeers(_ peers: [Peer], update: (Peer, Peer) -> Peer?) {
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
if let currentPeer = self.peerTable.get(peer.id) {
|
if let currentPeer = self.peerTable.get(peer.id) {
|
||||||
if let updatedPeer = update(currentPeer, peer) {
|
if let updatedPeer = update(currentPeer, peer) {
|
||||||
@ -731,28 +730,28 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func replaceContactPeerIds(_ peerIds: Set<PeerId>) {
|
fileprivate func replaceContactPeerIds(_ peerIds: Set<PeerId>) {
|
||||||
self.contactsTable.replace(peerIds)
|
self.contactsTable.replace(peerIds)
|
||||||
|
|
||||||
self.currentReplacedContactPeerIds = peerIds
|
self.currentReplacedContactPeerIds = peerIds
|
||||||
}
|
}
|
||||||
|
|
||||||
private func replaceRecentPeerIds(_ peerIds: [PeerId]) {
|
fileprivate func replaceRecentPeerIds(_ peerIds: [PeerId]) {
|
||||||
self.peerRatingTable.replace(items: peerIds)
|
self.peerRatingTable.replace(items: peerIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMessage(_ index: MessageIndex, update: (Message) -> StoreMessage) {
|
fileprivate func updateMessage(_ index: MessageIndex, update: (Message) -> StoreMessage) {
|
||||||
if let intermediateMessage = self.messageHistoryTable.getMessage(index) {
|
if let intermediateMessage = self.messageHistoryTable.getMessage(index) {
|
||||||
let message = self.renderIntermediateMessage(intermediateMessage)
|
let message = self.renderIntermediateMessage(intermediateMessage)
|
||||||
self.messageHistoryTable.updateMessage(index.id, message: update(message), operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
self.messageHistoryTable.updateMessage(index.id, message: update(message), operationsByPeerId: &self.currentOperationsByPeerId, unsentMessageOperations: &self.currentUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMedia(_ id: MediaId, update: Media?) {
|
fileprivate func updateMedia(_ id: MediaId, update: Media?) {
|
||||||
self.messageHistoryTable.updateMedia(id, media: update, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia)
|
self.messageHistoryTable.updateMedia(id, media: update, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func filterStoredMessageIds(_ messageIds: Set<MessageId>) -> Set<MessageId> {
|
fileprivate func filterStoredMessageIds(_ messageIds: Set<MessageId>) -> Set<MessageId> {
|
||||||
var filteredIds = Set<MessageId>()
|
var filteredIds = Set<MessageId>()
|
||||||
|
|
||||||
for id in messageIds {
|
for id in messageIds {
|
||||||
@ -764,7 +763,7 @@ public final class Postbox {
|
|||||||
return filteredIds
|
return filteredIds
|
||||||
}
|
}
|
||||||
|
|
||||||
public func modify<T>(_ f: (Modifier) -> T) -> Signal<T, NoError> {
|
public func modify<T>(_ f: @escaping(Modifier) -> T) -> Signal<T, NoError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
self.queue.justDispatch {
|
self.queue.justDispatch {
|
||||||
self.valueBox.begin()
|
self.valueBox.begin()
|
||||||
|
@ -3,6 +3,5 @@ module sqlcipher {
|
|||||||
header "sqlcipher/sqlite3ext.h"
|
header "sqlcipher/sqlite3ext.h"
|
||||||
header "sqlcipher/SQLite-Bridging.h"
|
header "sqlcipher/SQLite-Bridging.h"
|
||||||
header "sqlcipher/fts3_tokenizer.h"
|
header "sqlcipher/fts3_tokenizer.h"
|
||||||
header "../../submodules/lmdb/libraries/liblmdb/lmdb.h"
|
|
||||||
export *
|
export *
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ import Foundation
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
|
||||||
public struct RandomAccessResourceStoreRange {
|
public struct RandomAccessResourceStoreRange {
|
||||||
private let offset: Int
|
fileprivate let offset: Int
|
||||||
private let data: Data
|
fileprivate let data: Data
|
||||||
|
|
||||||
public init(offset: Int, data: Data) {
|
public init(offset: Int, data: Data) {
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
@ -19,16 +19,16 @@ public enum RandomAccessResourceDataRangeMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class RandomAccessBlockRangeListener: Hashable {
|
private final class RandomAccessBlockRangeListener: Hashable {
|
||||||
private let id: Int32
|
fileprivate let id: Int32
|
||||||
private let range: Range<Int>
|
private let range: Range<Int>
|
||||||
private let blockSize: Int
|
private let blockSize: Int
|
||||||
private let blocks: Range<Int>
|
private let blocks: Range<Int>
|
||||||
private let mode: RandomAccessResourceDataRangeMode
|
private let mode: RandomAccessResourceDataRangeMode
|
||||||
private let updated: (Data) -> Void
|
private let updated: (Data) -> Void
|
||||||
|
|
||||||
private var missingBlocks: Set<Int>
|
fileprivate var missingBlocks: Set<Int>
|
||||||
|
|
||||||
init(id: Int32, range: Range<Int>, blockSize: Int, blocks: Range<Int>, missingBlocks: Set<Int>, mode: RandomAccessResourceDataRangeMode, updated: (Data) -> Void) {
|
init(id: Int32, range: Range<Int>, blockSize: Int, blocks: Range<Int>, missingBlocks: Set<Int>, mode: RandomAccessResourceDataRangeMode, updated: @escaping(Data) -> Void) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.range = range
|
self.range = range
|
||||||
self.blockSize = blockSize
|
self.blockSize = blockSize
|
||||||
@ -42,7 +42,7 @@ private final class RandomAccessBlockRangeListener: Hashable {
|
|||||||
return Int(self.id)
|
return Int(self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateMissingBlocks(addedBlocks: Set<Int>, fetchData: @noescape(Range<Int>) -> Data) {
|
func updateMissingBlocks(addedBlocks: Set<Int>, fetchData: (Range<Int>) -> Data) {
|
||||||
if self.missingBlocks.isEmpty {
|
if self.missingBlocks.isEmpty {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ public final class RandomAccessMediaResourceContext {
|
|||||||
|
|
||||||
private var fetchRange: (Range<Int>) -> Disposable
|
private var fetchRange: (Range<Int>) -> Disposable
|
||||||
|
|
||||||
public init(path: String, size: Int, fetchRange: (Range<Int>) -> Disposable) {
|
public init(path: String, size: Int, fetchRange: @escaping(Range<Int>) -> Disposable) {
|
||||||
self.path = path
|
self.path = path
|
||||||
self.size = size
|
self.size = size
|
||||||
self.fetchRange = fetchRange
|
self.fetchRange = fetchRange
|
||||||
@ -308,7 +308,7 @@ public final class RandomAccessMediaResourceContext {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addListenerForData(in range: Range<Int>, mode: RandomAccessResourceDataRangeMode, updated: (Data) -> Void) -> Int32 {
|
public func addListenerForData(in range: Range<Int>, mode: RandomAccessResourceDataRangeMode, updated: @escaping (Data) -> Void) -> Int32 {
|
||||||
let firstBlock = range.lowerBound / self.blockSize
|
let firstBlock = range.lowerBound / self.blockSize
|
||||||
let lastBlock = range.upperBound / self.blockSize + (range.upperBound % self.blockSize == 0 ? 0 : 1)
|
let lastBlock = range.upperBound / self.blockSize + (range.upperBound % self.blockSize == 0 ? 0 : 1)
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import SwiftSignalKit
|
|||||||
private struct SqlitePreparedStatement {
|
private struct SqlitePreparedStatement {
|
||||||
let statement: OpaquePointer?
|
let statement: OpaquePointer?
|
||||||
|
|
||||||
func bind(_ index: Int, data: UnsafePointer<Void>, length: Int) {
|
func bind(_ index: Int, data: UnsafeRawPointer, length: Int) {
|
||||||
sqlite3_bind_blob(statement, Int32(index), data, Int32(length), nil)
|
sqlite3_bind_blob(statement, Int32(index), data, Int32(length), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +101,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
checkpoints.set(nil)
|
checkpoints.set(nil)
|
||||||
lock.lock()
|
lock.lock()
|
||||||
|
|
||||||
do {
|
let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
|
||||||
try FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
} catch _ { }
|
|
||||||
let path = basePath + "/db_sqlite"
|
let path = basePath + "/db_sqlite"
|
||||||
let database = Database(path)
|
let database = Database(path)
|
||||||
|
|
||||||
@ -115,6 +113,16 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
database.execute("PRAGMA temp_store=MEMORY")
|
database.execute("PRAGMA temp_store=MEMORY")
|
||||||
database.execute("PRAGMA wal_autocheckpoint=200")
|
database.execute("PRAGMA wal_autocheckpoint=200")
|
||||||
database.execute("PRAGMA journal_size_limit=1536")
|
database.execute("PRAGMA journal_size_limit=1536")
|
||||||
|
|
||||||
|
/*var statement: OpaquePointer? = nil
|
||||||
|
sqlite3_prepare_v2(database.handle, "PRAGMA integrity_check", -1, &statement, nil)
|
||||||
|
let preparedStatement = SqlitePreparedStatement(statement: statement)
|
||||||
|
if preparedStatement.step() {
|
||||||
|
let value = preparedStatement.stringAt(0)
|
||||||
|
print("integrity_check: \(value)")
|
||||||
|
}
|
||||||
|
preparedStatement.destroy()*/
|
||||||
|
|
||||||
sqlite3_busy_timeout(database.handle, 10000000)
|
sqlite3_busy_timeout(database.handle, 10000000)
|
||||||
|
|
||||||
let result = self.getUserVersion(database)
|
let result = self.getUserVersion(database)
|
||||||
@ -129,7 +137,7 @@ public final class SqliteValueBox: ValueBox {
|
|||||||
lock.unlock()
|
lock.unlock()
|
||||||
|
|
||||||
checkpoints.set((Signal<Void, NoError>.single(Void()) |> delay(10.0, queue: Queue.concurrentDefaultQueue()) |> restart).start(next: { [weak self] _ in
|
checkpoints.set((Signal<Void, NoError>.single(Void()) |> delay(10.0, queue: Queue.concurrentDefaultQueue()) |> restart).start(next: { [weak self] _ in
|
||||||
if let strongSelf = self where strongSelf.database != nil {
|
if let strongSelf = self , strongSelf.database != nil {
|
||||||
strongSelf.lock.lock()
|
strongSelf.lock.lock()
|
||||||
var nLog: Int32 = 0
|
var nLog: Int32 = 0
|
||||||
var nFrames: Int32 = 0
|
var nFrames: Int32 = 0
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
private final class ValueBoxKeyImpl {
|
private final class ValueBoxKeyImpl {
|
||||||
let memory: UnsafeMutablePointer<Void>
|
let memory: UnsafeMutableRawPointer
|
||||||
|
|
||||||
init(memory: UnsafeMutablePointer<Void>) {
|
init(memory: UnsafeMutableRawPointer) {
|
||||||
self.memory = memory
|
self.memory = memory
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,12 +13,12 @@ private final class ValueBoxKeyImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
||||||
public let memory: UnsafeMutablePointer<Void>
|
public let memory: UnsafeMutableRawPointer
|
||||||
public let length: Int
|
public let length: Int
|
||||||
private let impl: ValueBoxKeyImpl
|
private let impl: ValueBoxKeyImpl
|
||||||
|
|
||||||
public init(length: Int) {
|
public init(length: Int) {
|
||||||
self.memory = malloc(length)
|
self.memory = malloc(length)!
|
||||||
self.length = length
|
self.length = length
|
||||||
self.impl = ValueBoxKeyImpl(memory: self.memory)
|
self.impl = ValueBoxKeyImpl(memory: self.memory)
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
|||||||
self.memory = malloc(data.count)
|
self.memory = malloc(data.count)
|
||||||
self.length = data.count
|
self.length = data.count
|
||||||
self.impl = ValueBoxKeyImpl(memory: self.memory)
|
self.impl = ValueBoxKeyImpl(memory: self.memory)
|
||||||
data.copyBytes(to: UnsafeMutablePointer<UInt8>(self.memory), count: data.count)
|
data.copyBytes(to: self.memory.assumingMemoryBound(to: UInt8.self), count: data.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ buffer: MemoryBuffer) {
|
public init(_ buffer: MemoryBuffer) {
|
||||||
@ -92,7 +92,7 @@ public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
|||||||
public var successor: ValueBoxKey {
|
public var successor: ValueBoxKey {
|
||||||
let key = ValueBoxKey(length: self.length)
|
let key = ValueBoxKey(length: self.length)
|
||||||
memcpy(key.memory, self.memory, self.length)
|
memcpy(key.memory, self.memory, self.length)
|
||||||
let memory = UnsafeMutablePointer<UInt8>(key.memory)
|
let memory = key.memory.assumingMemoryBound(to: UInt8.self)
|
||||||
var i = self.length - 1
|
var i = self.length - 1
|
||||||
while i >= 0 {
|
while i >= 0 {
|
||||||
var byte = memory[i]
|
var byte = memory[i]
|
||||||
@ -112,7 +112,7 @@ public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
|||||||
public var predecessor: ValueBoxKey {
|
public var predecessor: ValueBoxKey {
|
||||||
let key = ValueBoxKey(length: self.length)
|
let key = ValueBoxKey(length: self.length)
|
||||||
memcpy(key.memory, self.memory, self.length)
|
memcpy(key.memory, self.memory, self.length)
|
||||||
let memory = UnsafeMutablePointer<UInt8>(key.memory)
|
let memory = key.memory.assumingMemoryBound(to: UInt8.self)
|
||||||
var i = self.length - 1
|
var i = self.length - 1
|
||||||
while i >= 0 {
|
while i >= 0 {
|
||||||
var byte = memory[i]
|
var byte = memory[i]
|
||||||
@ -131,7 +131,7 @@ public struct ValueBoxKey: Comparable, CustomStringConvertible {
|
|||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
let string = NSMutableString()
|
let string = NSMutableString()
|
||||||
let memory = UnsafeMutablePointer<UInt8>(self.memory)
|
let memory = self.memory.assumingMemoryBound(to: UInt8.self)
|
||||||
for i in 0 ..< self.length {
|
for i in 0 ..< self.length {
|
||||||
let byte: Int = Int(memory[i])
|
let byte: Int = Int(memory[i])
|
||||||
string.appendFormat("%02x", byte)
|
string.appendFormat("%02x", byte)
|
||||||
@ -144,7 +144,7 @@ public func ==(lhs: ValueBoxKey, rhs: ValueBoxKey) -> Bool {
|
|||||||
return lhs.length == rhs.length && memcmp(lhs.memory, rhs.memory, lhs.length) == 0
|
return lhs.length == rhs.length && memcmp(lhs.memory, rhs.memory, lhs.length) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private func mdb_cmp_memn(_ a_memory: UnsafeMutablePointer<Void>, _ a_length: Int, _ b_memory: UnsafeMutablePointer<Void>, _ b_length: Int) -> Int
|
private func mdb_cmp_memn(_ a_memory: UnsafeMutableRawPointer, _ a_length: Int, _ b_memory: UnsafeMutableRawPointer, _ b_length: Int) -> Int
|
||||||
{
|
{
|
||||||
var diff: Int = 0
|
var diff: Int = 0
|
||||||
var len_diff: Int = 0
|
var len_diff: Int = 0
|
||||||
|
@ -35,7 +35,7 @@ final class ViewTracker {
|
|||||||
private var synchronizeReadStatesView: MutableSynchronizePeerReadStatesView
|
private var synchronizeReadStatesView: MutableSynchronizePeerReadStatesView
|
||||||
private let synchronizePeerReadStatesViewSubscribers = Bag<ValuePipe<SynchronizePeerReadStatesView>>()
|
private let synchronizePeerReadStatesViewSubscribers = Bag<ValuePipe<SynchronizePeerReadStatesView>>()
|
||||||
|
|
||||||
init(queue: Queue, fetchEarlierHistoryEntries: (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchLaterHistoryEntries: (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchEarlierChatEntries: (MessageIndex?, Int) -> [MutableChatListEntry], fetchLaterChatEntries: (MessageIndex?, Int) -> [MutableChatListEntry], fetchAnchorIndex: (MessageId) -> MessageHistoryAnchorIndex?, renderMessage: (IntermediateMessage) -> Message, getPeer: (PeerId) -> Peer?, unsentMessageIndices: [MessageIndex], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
init(queue: Queue, fetchEarlierHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchLaterHistoryEntries: @escaping (PeerId, MessageIndex?, Int, MessageTags?) -> [MutableMessageHistoryEntry], fetchEarlierChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchLaterChatEntries: @escaping (MessageIndex?, Int) -> [MutableChatListEntry], fetchAnchorIndex: @escaping (MessageId) -> MessageHistoryAnchorIndex?, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, unsentMessageIndices: [MessageIndex], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.fetchEarlierHistoryEntries = fetchEarlierHistoryEntries
|
self.fetchEarlierHistoryEntries = fetchEarlierHistoryEntries
|
||||||
self.fetchLaterHistoryEntries = fetchLaterHistoryEntries
|
self.fetchLaterHistoryEntries = fetchLaterHistoryEntries
|
||||||
@ -142,7 +142,7 @@ final class ViewTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshViewsDueToExternalTransaction(fetchAroundChatEntries: (index: MessageIndex, count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (index: MessageIndex, count: Int, tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsendMessageIndices: () -> [MessageIndex], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
|
func refreshViewsDueToExternalTransaction(fetchAroundChatEntries: (_ index: MessageIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsendMessageIndices: () -> [MessageIndex], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||||
var updateTrackedHolesPeerIds: [PeerId] = []
|
var updateTrackedHolesPeerIds: [PeerId] = []
|
||||||
|
|
||||||
for (peerId, bag) in self.messageHistoryViews {
|
for (peerId, bag) in self.messageHistoryViews {
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,360 +0,0 @@
|
|||||||
/** @file midl.c
|
|
||||||
* @brief ldap bdb back-end ID List functions */
|
|
||||||
/* $OpenLDAP$ */
|
|
||||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
||||||
*
|
|
||||||
* Copyright 2000-2014 The OpenLDAP Foundation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted only as authorized by the OpenLDAP
|
|
||||||
* Public License.
|
|
||||||
*
|
|
||||||
* A copy of this license is available in the file LICENSE in the
|
|
||||||
* top-level directory of the distribution or, alternatively, at
|
|
||||||
* <http://www.OpenLDAP.org/license.html>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "midl.h"
|
|
||||||
|
|
||||||
/** @defgroup internal LMDB Internals
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/** @defgroup idls ID List Management
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
#define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
|
|
||||||
|
|
||||||
unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* binary search of id in ids
|
|
||||||
* if found, returns position of id
|
|
||||||
* if not found, returns first position greater than id
|
|
||||||
*/
|
|
||||||
unsigned base = 0;
|
|
||||||
unsigned cursor = 1;
|
|
||||||
int val = 0;
|
|
||||||
unsigned n = ids[0];
|
|
||||||
|
|
||||||
while( 0 < n ) {
|
|
||||||
unsigned pivot = n >> 1;
|
|
||||||
cursor = base + pivot + 1;
|
|
||||||
val = CMP( ids[cursor], id );
|
|
||||||
|
|
||||||
if( val < 0 ) {
|
|
||||||
n = pivot;
|
|
||||||
|
|
||||||
} else if ( val > 0 ) {
|
|
||||||
base = cursor;
|
|
||||||
n -= pivot + 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( val > 0 ) {
|
|
||||||
++cursor;
|
|
||||||
}
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 /* superseded by append/sort */
|
|
||||||
int mdb_midl_insert( MDB_IDL ids, MDB_ID id )
|
|
||||||
{
|
|
||||||
unsigned x, i;
|
|
||||||
|
|
||||||
x = mdb_midl_search( ids, id );
|
|
||||||
assert( x > 0 );
|
|
||||||
|
|
||||||
if( x < 1 ) {
|
|
||||||
/* internal error */
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( x <= ids[0] && ids[x] == id ) {
|
|
||||||
/* duplicate */
|
|
||||||
assert(0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ++ids[0] >= MDB_IDL_DB_MAX ) {
|
|
||||||
/* no room */
|
|
||||||
--ids[0];
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* insert id */
|
|
||||||
for (i=ids[0]; i>x; i--)
|
|
||||||
ids[i] = ids[i-1];
|
|
||||||
ids[x] = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MDB_IDL mdb_midl_alloc(int num)
|
|
||||||
{
|
|
||||||
MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID));
|
|
||||||
if (ids) {
|
|
||||||
*ids++ = num;
|
|
||||||
*ids = 0;
|
|
||||||
}
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mdb_midl_free(MDB_IDL ids)
|
|
||||||
{
|
|
||||||
if (ids)
|
|
||||||
free(ids-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_shrink( MDB_IDL *idp )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
if (*(--ids) > MDB_IDL_UM_MAX &&
|
|
||||||
(ids = realloc(ids, (MDB_IDL_UM_MAX+1) * sizeof(MDB_ID))))
|
|
||||||
{
|
|
||||||
*ids++ = MDB_IDL_UM_MAX;
|
|
||||||
*idp = ids;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
|
||||||
{
|
|
||||||
MDB_IDL idn = *idp-1;
|
|
||||||
/* grow it */
|
|
||||||
idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID));
|
|
||||||
if (!idn)
|
|
||||||
return ENOMEM;
|
|
||||||
*idn++ += num;
|
|
||||||
*idp = idn;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_need( MDB_IDL *idp, unsigned num )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
num += ids[0];
|
|
||||||
if (num > ids[-1]) {
|
|
||||||
num = (num + num/4 + (256 + 2)) & -256;
|
|
||||||
if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
|
|
||||||
return ENOMEM;
|
|
||||||
*ids++ = num - 2;
|
|
||||||
*idp = ids;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0] >= ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, MDB_IDL_UM_MAX))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
ids[0]++;
|
|
||||||
ids[ids[0]] = id;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
|
|
||||||
{
|
|
||||||
MDB_IDL ids = *idp;
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0] + app[0] >= ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, app[0]))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID));
|
|
||||||
ids[0] += app[0];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
|
|
||||||
{
|
|
||||||
MDB_ID *ids = *idp, len = ids[0];
|
|
||||||
/* Too big? */
|
|
||||||
if (len + n > ids[-1]) {
|
|
||||||
if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX))
|
|
||||||
return ENOMEM;
|
|
||||||
ids = *idp;
|
|
||||||
}
|
|
||||||
ids[0] = len + n;
|
|
||||||
ids += len;
|
|
||||||
while (n)
|
|
||||||
ids[n--] = id++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge )
|
|
||||||
{
|
|
||||||
MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k;
|
|
||||||
idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */
|
|
||||||
old_id = idl[j];
|
|
||||||
while (i) {
|
|
||||||
merge_id = merge[i--];
|
|
||||||
for (; old_id < merge_id; old_id = idl[--j])
|
|
||||||
idl[k--] = old_id;
|
|
||||||
idl[k--] = merge_id;
|
|
||||||
}
|
|
||||||
idl[0] = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quicksort + Insertion sort for small arrays */
|
|
||||||
|
|
||||||
#define SMALL 8
|
|
||||||
#define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
|
|
||||||
|
|
||||||
void
|
|
||||||
mdb_midl_sort( MDB_IDL ids )
|
|
||||||
{
|
|
||||||
/* Max possible depth of int-indexed tree * 2 items/level */
|
|
||||||
int istack[sizeof(int)*CHAR_BIT * 2];
|
|
||||||
int i,j,k,l,ir,jstack;
|
|
||||||
MDB_ID a, itmp;
|
|
||||||
|
|
||||||
ir = (int)ids[0];
|
|
||||||
l = 1;
|
|
||||||
jstack = 0;
|
|
||||||
for(;;) {
|
|
||||||
if (ir - l < SMALL) { /* Insertion sort */
|
|
||||||
for (j=l+1;j<=ir;j++) {
|
|
||||||
a = ids[j];
|
|
||||||
for (i=j-1;i>=1;i--) {
|
|
||||||
if (ids[i] >= a) break;
|
|
||||||
ids[i+1] = ids[i];
|
|
||||||
}
|
|
||||||
ids[i+1] = a;
|
|
||||||
}
|
|
||||||
if (jstack == 0) break;
|
|
||||||
ir = istack[jstack--];
|
|
||||||
l = istack[jstack--];
|
|
||||||
} else {
|
|
||||||
k = (l + ir) >> 1; /* Choose median of left, center, right */
|
|
||||||
MIDL_SWAP(ids[k], ids[l+1]);
|
|
||||||
if (ids[l] < ids[ir]) {
|
|
||||||
MIDL_SWAP(ids[l], ids[ir]);
|
|
||||||
}
|
|
||||||
if (ids[l+1] < ids[ir]) {
|
|
||||||
MIDL_SWAP(ids[l+1], ids[ir]);
|
|
||||||
}
|
|
||||||
if (ids[l] < ids[l+1]) {
|
|
||||||
MIDL_SWAP(ids[l], ids[l+1]);
|
|
||||||
}
|
|
||||||
i = l+1;
|
|
||||||
j = ir;
|
|
||||||
a = ids[l+1];
|
|
||||||
for(;;) {
|
|
||||||
do i++; while(ids[i] > a);
|
|
||||||
do j--; while(ids[j] < a);
|
|
||||||
if (j < i) break;
|
|
||||||
MIDL_SWAP(ids[i],ids[j]);
|
|
||||||
}
|
|
||||||
ids[l+1] = ids[j];
|
|
||||||
ids[j] = a;
|
|
||||||
jstack += 2;
|
|
||||||
if (ir-i+1 >= j-l) {
|
|
||||||
istack[jstack] = ir;
|
|
||||||
istack[jstack-1] = i;
|
|
||||||
ir = j-1;
|
|
||||||
} else {
|
|
||||||
istack[jstack] = j-1;
|
|
||||||
istack[jstack-1] = l;
|
|
||||||
l = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* binary search of id in ids
|
|
||||||
* if found, returns position of id
|
|
||||||
* if not found, returns first position greater than id
|
|
||||||
*/
|
|
||||||
unsigned base = 0;
|
|
||||||
unsigned cursor = 1;
|
|
||||||
int val = 0;
|
|
||||||
unsigned n = (unsigned)ids[0].mid;
|
|
||||||
|
|
||||||
while( 0 < n ) {
|
|
||||||
unsigned pivot = n >> 1;
|
|
||||||
cursor = base + pivot + 1;
|
|
||||||
val = CMP( id, ids[cursor].mid );
|
|
||||||
|
|
||||||
if( val < 0 ) {
|
|
||||||
n = pivot;
|
|
||||||
|
|
||||||
} else if ( val > 0 ) {
|
|
||||||
base = cursor;
|
|
||||||
n -= pivot + 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( val > 0 ) {
|
|
||||||
++cursor;
|
|
||||||
}
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id )
|
|
||||||
{
|
|
||||||
unsigned x, i;
|
|
||||||
|
|
||||||
x = mdb_mid2l_search( ids, id->mid );
|
|
||||||
|
|
||||||
if( x < 1 ) {
|
|
||||||
/* internal error */
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
|
||||||
/* duplicate */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ids[0].mid >= MDB_IDL_UM_MAX ) {
|
|
||||||
/* too big */
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* insert id */
|
|
||||||
ids[0].mid++;
|
|
||||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
|
||||||
ids[i] = ids[i-1];
|
|
||||||
ids[x] = *id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
|
||||||
{
|
|
||||||
/* Too big? */
|
|
||||||
if (ids[0].mid >= MDB_IDL_UM_MAX) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
ids[0].mid++;
|
|
||||||
ids[ids[0].mid] = *id;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
/** @} */
|
|
@ -1,186 +0,0 @@
|
|||||||
/** @file midl.h
|
|
||||||
* @brief LMDB ID List header file.
|
|
||||||
*
|
|
||||||
* This file was originally part of back-bdb but has been
|
|
||||||
* modified for use in libmdb. Most of the macros defined
|
|
||||||
* in this file are unused, just left over from the original.
|
|
||||||
*
|
|
||||||
* This file is only used internally in libmdb and its definitions
|
|
||||||
* are not exposed publicly.
|
|
||||||
*/
|
|
||||||
/* $OpenLDAP$ */
|
|
||||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
||||||
*
|
|
||||||
* Copyright 2000-2014 The OpenLDAP Foundation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted only as authorized by the OpenLDAP
|
|
||||||
* Public License.
|
|
||||||
*
|
|
||||||
* A copy of this license is available in the file LICENSE in the
|
|
||||||
* top-level directory of the distribution or, alternatively, at
|
|
||||||
* <http://www.OpenLDAP.org/license.html>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MDB_MIDL_H_
|
|
||||||
#define _MDB_MIDL_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @defgroup internal LMDB Internals
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup idls ID List Management
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
|
||||||
* Preferably it should have the same size as a pointer.
|
|
||||||
*/
|
|
||||||
typedef size_t MDB_ID;
|
|
||||||
|
|
||||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
|
||||||
* element of the array is a counter for how many actual
|
|
||||||
* IDs are in the list. In the original back-bdb code, IDLs are
|
|
||||||
* sorted in ascending order. For libmdb IDLs are sorted in
|
|
||||||
* descending order.
|
|
||||||
*/
|
|
||||||
typedef MDB_ID *MDB_IDL;
|
|
||||||
|
|
||||||
/* IDL sizes - likely should be even bigger
|
|
||||||
* limiting factors: sizeof(ID), thread stack size
|
|
||||||
*/
|
|
||||||
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
|
||||||
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
|
||||||
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
|
||||||
|
|
||||||
#define MDB_IDL_DB_MAX (MDB_IDL_DB_SIZE-1)
|
|
||||||
#define MDB_IDL_UM_MAX (MDB_IDL_UM_SIZE-1)
|
|
||||||
|
|
||||||
#define MDB_IDL_SIZEOF(ids) (((ids)[0]+1) * sizeof(MDB_ID))
|
|
||||||
#define MDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
|
|
||||||
#define MDB_IDL_CPY( dst, src ) (memcpy( dst, src, MDB_IDL_SIZEOF( src ) ))
|
|
||||||
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
|
||||||
#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
|
|
||||||
|
|
||||||
/** Current max length of an #mdb_midl_alloc()ed IDL */
|
|
||||||
#define MDB_IDL_ALLOCLEN( ids ) ( (ids)[-1] )
|
|
||||||
|
|
||||||
/** Append ID to IDL. The IDL must be big enough. */
|
|
||||||
#define mdb_midl_xappend(idl, id) do { \
|
|
||||||
MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \
|
|
||||||
xidl[xlen] = (id); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/** Search for an ID in an IDL.
|
|
||||||
* @param[in] ids The IDL to search.
|
|
||||||
* @param[in] id The ID to search for.
|
|
||||||
* @return The index of the first ID greater than or equal to \b id.
|
|
||||||
*/
|
|
||||||
unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id );
|
|
||||||
|
|
||||||
/** Allocate an IDL.
|
|
||||||
* Allocates memory for an IDL of the given size.
|
|
||||||
* @return IDL on success, NULL on failure.
|
|
||||||
*/
|
|
||||||
MDB_IDL mdb_midl_alloc(int num);
|
|
||||||
|
|
||||||
/** Free an IDL.
|
|
||||||
* @param[in] ids The IDL to free.
|
|
||||||
*/
|
|
||||||
void mdb_midl_free(MDB_IDL ids);
|
|
||||||
|
|
||||||
/** Shrink an IDL.
|
|
||||||
* Return the IDL to the default size if it has grown larger.
|
|
||||||
* @param[in,out] idp Address of the IDL to shrink.
|
|
||||||
* @return 0 on no change, non-zero if shrunk.
|
|
||||||
*/
|
|
||||||
int mdb_midl_shrink(MDB_IDL *idp);
|
|
||||||
|
|
||||||
/** Make room for num additional elements in an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL.
|
|
||||||
* @param[in] num Number of elements to make room for.
|
|
||||||
* @return 0 on success, ENOMEM on failure.
|
|
||||||
*/
|
|
||||||
int mdb_midl_need(MDB_IDL *idp, unsigned num);
|
|
||||||
|
|
||||||
/** Append an ID onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] id The ID to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
|
|
||||||
|
|
||||||
/** Append an IDL onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] app The IDL to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
|
|
||||||
|
|
||||||
/** Append an ID range onto an IDL.
|
|
||||||
* @param[in,out] idp Address of the IDL to append to.
|
|
||||||
* @param[in] id The lowest ID to append.
|
|
||||||
* @param[in] n Number of IDs to append.
|
|
||||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
|
||||||
*/
|
|
||||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n );
|
|
||||||
|
|
||||||
/** Merge an IDL onto an IDL. The destination IDL must be big enough.
|
|
||||||
* @param[in] idl The IDL to merge into.
|
|
||||||
* @param[in] merge The IDL to merge.
|
|
||||||
*/
|
|
||||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge );
|
|
||||||
|
|
||||||
/** Sort an IDL.
|
|
||||||
* @param[in,out] ids The IDL to sort.
|
|
||||||
*/
|
|
||||||
void mdb_midl_sort( MDB_IDL ids );
|
|
||||||
|
|
||||||
/** An ID2 is an ID/pointer pair.
|
|
||||||
*/
|
|
||||||
typedef struct MDB_ID2 {
|
|
||||||
MDB_ID mid; /**< The ID */
|
|
||||||
void *mptr; /**< The pointer */
|
|
||||||
} MDB_ID2;
|
|
||||||
|
|
||||||
/** An ID2L is an ID2 List, a sorted array of ID2s.
|
|
||||||
* The first element's \b mid member is a count of how many actual
|
|
||||||
* elements are in the array. The \b mptr member of the first element is unused.
|
|
||||||
* The array is sorted in ascending order by \b mid.
|
|
||||||
*/
|
|
||||||
typedef MDB_ID2 *MDB_ID2L;
|
|
||||||
|
|
||||||
/** Search for an ID in an ID2L.
|
|
||||||
* @param[in] ids The ID2L to search.
|
|
||||||
* @param[in] id The ID to search for.
|
|
||||||
* @return The index of the first ID2 whose \b mid member is greater than or equal to \b id.
|
|
||||||
*/
|
|
||||||
unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id );
|
|
||||||
|
|
||||||
|
|
||||||
/** Insert an ID2 into a ID2L.
|
|
||||||
* @param[in,out] ids The ID2L to insert into.
|
|
||||||
* @param[in] id The ID2 to insert.
|
|
||||||
* @return 0 on success, -1 if the ID was already present in the ID2L.
|
|
||||||
*/
|
|
||||||
int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
|
||||||
|
|
||||||
/** Append an ID2 into a ID2L.
|
|
||||||
* @param[in,out] ids The ID2L to append into.
|
|
||||||
* @param[in] id The ID2 to append.
|
|
||||||
* @return 0 on success, -2 if the ID2L is too big.
|
|
||||||
*/
|
|
||||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
/** @} */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* _MDB_MIDL_H_ */
|
|
Loading…
x
Reference in New Issue
Block a user