Home telegram - table
Post
Cancel

telegram - table

ValueBoxKey

ValueBoxKeyImpl

class ValueBoxKeyImpl

1
2
3
4
5
let memory: UnsafeMutableRawPointer

deinit {
    free(self.memory)
}

struct ValueBoxKey:Equatable,Hashable,Comparable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
public let memory: UnsafeMutableRawPointer
public let length: Int
private let impl: ValueBoxKeyImpl

// utf8 encoding with allowLossyConversion option
// -[Data copyBytesTo:count:]
public init(_ value: String) {
    let data = value.data(using: .utf8, allowLossyConversion: true) ?? Data()
  // malloc
    self.memory = malloc(data.count)
    self.length = data.count
    self.impl = ValueBoxKeyImpl(memory: self.memory)
    data.copyBytes(to: self.memory.assumingMemoryBound(to: UInt8.self), count: data.count)
}

// init with memoryBuffer
public init(_ buffer: MemoryBuffer) {
  // malloc
    self.memory = malloc(buffer.length)
    self.length = buffer.length
    self.impl = ValueBoxKeyImpl(memory: self.memory)
  // copy buffet.memory to self.memory
    memcpy(self.memory, buffer.memory, buffer.length)
}

// copy bytes in data to self.memory + offset
public func setData(_ offset: Int, value: Data) {
    assert(offset >= 0 && offset + value.count <= self.length)
    let valueLength = value.count
    value.withUnsafeBytes { rawBytes -> Void in
        let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
        memcpy(self.memory + offset, bytes, valueLength)
    }
}

// copy bigEndian representation of value with 4 bytes to `self.memory + offset`
public func setInt32(_ offset: Int, value: Int32) {
    assert(offset >= 0 && offset + 4 <= self.length)
    var bigEndianValue = Int32(bigEndian: value)
    memcpy(self.memory + offset, &bigEndianValue, 4)
}

// copy bigEndian representation of value with 4 bytes to `self.memory + offset`
public func setUInt32(_ offset: Int, value: UInt32) {
    assert(offset >= 0 && offset + 4 <= self.length)
    var bigEndianValue = UInt32(bigEndian: value)
    memcpy(self.memory + offset, &bigEndianValue, 4)
}

// copy value with one byte to `self.memory + offset`
public func setInt8(_ offset: Int, value: Int8) {
    assert(offset >= 0 && offset + 1 <= self.length)
    var varValue = value
    memcpy(self.memory + offset, &varValue, 1)
}

// copy value with one byte to `self.memory + offset`
public func setUInt8(_ offset: Int, value: UInt8) {
    assert(offset >= 0 && offset + 1 <= self.length)
    var varValue = value
    memcpy(self.memory + offset, &varValue, 1)
}

// copy value with two bytes to `self.memory + offset`
public func setUInt16(_ offset: Int, value: UInt16) {
    assert(offset >= 0 && offset + 2 <= self.length)
    var varValue = value
    memcpy(self.memory + offset, &varValue, 2)
}

// copy 4 bytes from self.memory + offset as a Int32 bigEndian value
public func getInt32(_ offset: Int) -> Int32 {
    assert(offset >= 0 && offset + 4 <= self.length)
    var value: Int32 = 0
    memcpy(&value, self.memory + offset, 4)
    return Int32(bigEndian: value)
}

// copy 4 bytes from self.memory + offset as a UInt32 bigEndian value
public func getUInt32(_ offset: Int) -> UInt32 {
    assert(offset >= 0 && offset + 4 <= self.length)
    var value: UInt32 = 0
    memcpy(&value, self.memory + offset, 4)
    return UInt32(bigEndian: value)
}

// copy 8 bytes from `self.memory + offset` as a Int32 bigEndian value
public func getInt64(_ offset: Int) -> Int64 {
    assert(offset >= 0 && offset + 8 <= self.length)
    var value: Int64 = 0
    memcpy(&value, self.memory + offset, 8)
    return Int64(bigEndian: value)
}

// copy one byte from `self.memory + offset` as a Int8 value
public func getInt8(_ offset: Int) -> Int8 {
    assert(offset >= 0 && offset + 1 <= self.length)
    var value: Int8 = 0
    memcpy(&value, self.memory + offset, 1)
    return value
}

// copy one byte from `self.memory + offset` as a UInt8 value
public func getUInt8(_ offset: Int) -> UInt8 {
    assert(offset >= 0 && offset + 1 <= self.length)
    var value: UInt8 = 0
    memcpy(&value, self.memory + offset, 1)
    return value
}

// copy two bytes from `self.memory + offset` as a UInt16 value
public func getUInt16(_ offset: Int) -> UInt16 {
    assert(offset >= 0 && offset + 2 <= self.length)
    var value: UInt16 = 0
    memcpy(&value, self.memory + offset, 2)
    return value
}

// copy prefix length bytes to a new created `ValueBoxKey` 
public func prefix(_ length: Int) -> ValueBoxKey {
    assert(length <= self.length, "length <= self.length")
    let key = ValueBoxKey(length: length)
    memcpy(key.memory, self.memory, length)
    return key
}

// `memcmp` other's memory with self.prefix length memory bytes 
public func isPrefix(to other: ValueBoxKey) -> Bool {
    if self.length == 0 {
        return true
    } else if self.length <= other.length {
        return memcmp(self.memory, other.memory, self.length) == 0
    } else {
        return false
    }
}

// return the reverse result of self.memory in byte unit
public var reversed: ValueBoxKey {
    let key = ValueBoxKey(length: self.length)
    let keyMemory = key.memory.assumingMemoryBound(to: UInt8.self)
    let selfMemory = self.memory.assumingMemoryBound(to: UInt8.self)
    var i = self.length - 1
    while i >= 0 {
        keyMemory[i] = selfMemory[self.length - 1 - i]
        i -= 1
    }
    return key
}

// plus 1 to last byte
public var successor: ValueBoxKey {
    let key = ValueBoxKey(length: self.length)
    memcpy(key.memory, self.memory, self.length)
    let memory = key.memory.assumingMemoryBound(to: UInt8.self)
    var i = self.length - 1
    while i >= 0 {
        var byte = memory[i]
        if byte != 0xff {
            byte += 1
            memory[i] = byte
            break
        } else {
            byte = 0
            memory[i] = byte
        }
        i -= 1
    }
    return key
}

// the predecessor
// minus 1 from the last byte
public var predecessor: ValueBoxKey {
    let key = ValueBoxKey(length: self.length)
    memcpy(key.memory, self.memory, self.length)
    let memory = key.memory.assumingMemoryBound(to: UInt8.self)
    var i = self.length - 1
    while i >= 0 {
        var byte = memory[i]
        if byte != 0x00 {
            byte -= 1
            memory[i] = byte
            break
        } else {// 0x00 byte
            if i == 0 {// all bytes in self.memory are 0x00
              // return the memory with copied bytes from self.memory in 0 ... self.length - 1 range
              // with value [0x00 0xff 0xff ...]
                assert(self.length > 1)
                let previousKey = ValueBoxKey(length: self.length - 1)
                memcpy(previousKey.memory, self.memory, self.length - 1)
                return previousKey
            } else {// if not the first, then replace the 0x00 with 0xff
                byte = 0xff
                memory[i] = byte
            }
        }
        i -= 1
    }
    return key
}

// description
public var description: String {
    let string = NSMutableString()
    let memory = self.memory.assumingMemoryBound(to: UInt8.self)
    for i in 0 ..< self.length {
        let byte: Int = Int(memory[i])
      // dump every single byte with two bits hex representation
        string.appendFormat("%02x", byte)
    }
    return string as String
}

// utf8 encoded string of the bytes
public var stringValue: String {
    if let string = String(data: Data(bytes: self.memory, count: self.length), encoding: .utf8) {
        return string
    } else {
        return "<unavailable>"
    }
}

// utf8 encoded string of bytes in range
public func substringValue(_ range: Range<Int>) -> String? {
    assert(range.lowerBound >= 0 && range.upperBound <= self.length)
    return String(data: Data(bytes: self.memory.advanced(by: range.lowerBound), count: range.count), encoding: .utf8)
}

// hashable
public func hash(into hasher: inout Hasher) {
    hasher.combine(bytes: UnsafeRawBufferPointer(start: self.memory, count: self.length))
}

// memcmp
public static func ==(lhs: ValueBoxKey, rhs: ValueBoxKey) -> Bool {
    return lhs.length == rhs.length && memcmp(lhs.memory, rhs.memory, lhs.length) == 0
}

// mdb_cmp_memn
public static func <(lhs: ValueBoxKey, rhs: ValueBoxKey) -> Bool {
    return mdb_cmp_memn(lhs.memory, lhs.length, rhs.memory, rhs.length) < 0
}

// return a memory buffer with copies memory bytes
public func toMemoryBuffer() -> MemoryBuffer {
    let data = malloc(self.length)!
    memcpy(data, self.memory, self.length)
    return MemoryBuffer(memory: data, capacity: self.length, length: self.length, freeWhenDone: true)
}

// return new key with memory alignment [lhs.memory rhs.memory]
public static func +(lhs: ValueBoxKey, rhs: ValueBoxKey) -> ValueBoxKey {
    let result = ValueBoxKey(length: lhs.length + rhs.length)
    memcpy(result.memory, lhs.memory, lhs.length)
    memcpy(result.memory.advanced(by: lhs.length), rhs.memory, rhs.length)
    return result
}

mdb_cmp_memn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private func mdb_cmp_memn(_ a_memory: UnsafeMutableRawPointer, _ a_length: Int, _ b_memory: UnsafeMutableRawPointer, _ b_length: Int) -> Int
{
    var diff: Int = 0
    var len_diff: Int = 0
    var len: Int = 0 // min(a_length, b_length)
    
    len = a_length
    len_diff = a_length - b_length
    if len_diff > 0 {
        len = b_length
        len_diff = 1
    }
    
  // memcmp len bytes
    diff = Int(memcmp(a_memory, b_memory, len))
    return diff != 0 ? diff : len_diff < 0 ? -1 : len_diff
}

memcmp

  • <= the first byte that does not match in both memory blocks has a lower value in ptr1 than in ptr2 (if evaluated as unsigned char values)
  • =0 the contents of both memory blocks are equal
  • >0 the first byte that does not match in both memory blocks has a greater value in ptr1 than in ptr2 (if evaluated as unsigned char values)

ValueBox

enum ValueBoxFilterResult

1
2
3
case accept
case skip
case stop

protocol ValueBox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
func begin()
func commit()
func checkpoint()

func beginStats()
func endStats()

// evalute the records from start to end until the evaluation expression `values` return false
func range(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, values: (ValueBoxKey, ReadBuffer) -> Bool, limit: Int)

// evalute the records from start to end
// ignore the `skip` record
// accetp the `accept` record
// stop when reach a `stop` record
// break when acceptedCount reach the `limit`
// break when no records
func filteredRange(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, values: (ValueBoxKey, ReadBuffer) -> ValueBoxFilterResult, limit: Int)

// evalute the records from start to end
// ignore the `skip` record
// accetp the `accept` record
// stop when reach a `stop` record
// break when acceptedCount reach the `limit`
// break when no records
func filteredRange(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, keys: (ValueBoxKey) -> ValueBoxFilterResult, limit: Int)

// evalute the records from start to end until the evaluation expression `keys` return false
func range(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, keys: (ValueBoxKey) -> Bool, limit: Int)

// evalute the records until the evaluation expression `values` return false
func scan(_ table: ValueBoxTable, values: (ValueBoxKey, ReadBuffer) -> Bool)

// evalute the records until the evaluation expression `keys` return false
func scan(_ table: ValueBoxTable, keys: (ValueBoxKey) -> Bool)

// evalute the records until the evaluation expression `values` return false
func scanInt64(_ table: ValueBoxTable, values: (Int64, ReadBuffer) -> Bool)

// evalute the records until the evaluation expression `keys` return false
func scanInt64(_ table: ValueBoxTable, keys: (Int64) -> Bool)

// get value with key
func get(_ table: ValueBoxTable, key: ValueBoxKey) -> ReadBuffer?

// read the value blob incrementally
func read(_ table: ValueBoxTable, key: ValueBoxKey, _ process: (Int, (UnsafeMutableRawPointer, Int, Int) -> Void) -> Void)

// read & write the value blob incrementally
 func readWrite(_ table: ValueBoxTable, key: ValueBoxKey, _ process: (Int, (UnsafeMutableRawPointer, Int, Int) -> Void, (UnsafeRawPointer, Int, Int) -> Void) -> Void)

// whether the `value` associated with the `key` exists
func exists(_ table: ValueBoxTable, key: ValueBoxKey) -> Bool

// set `value` for `key`
func set(_ table: ValueBoxTable, key: ValueBoxKey, value: MemoryBuffer)

// remove with key
func remove(_ table: ValueBoxTable, key: ValueBoxKey, secure: Bool)

// update key from previousKey to updatedKey
func move(_ table: ValueBoxTable, from previousKey: ValueBoxKey, to updatedKey: ValueBoxKey)

// copy record with fromkey from fromTable to toTable with toKey
func copy(fromTable: ValueBoxTable, fromKey: ValueBoxKey, toTable: ValueBoxTable, toKey: ValueBoxKey)

// remove records with the key from start to end
func removeRange(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey)

// insert info full text table
/**
 guard let collectionIdData = collectionId.data(using: .utf8), let itemIdData = itemId.data(using: .utf8), let contentsData = contents.data(using: .utf8), let tagsData = tags.data(using: .utf8) else {
            return
        }

sqlite3_prepare_v2(self.database.handle, "INSERT INTO ft\(table.id) (collectionId, itemId, contents, tags) VALUES(?, ?, ?, ?)", -1, &statement, nil)
*/
func fullTextSet(_ table: ValueBoxFullTextTable, collectionId: String, itemId: String, contents: String, tags: String)

// evalute the records with associated given values
// until the evaluation expression `values` return false
func fullTextMatch(_ table: ValueBoxFullTextTable, collectionId: String?, query: String, tags: String?, values: (String, String) -> Bool)

// remove records with associated itemid
func fullTextRemove(_ table: ValueBoxFullTextTable, itemId: String, secure: Bool)

// empty the table
func removeAllFromTable(_ table: ValueBoxTable)

// drop the table
func removeTable(_ table: ValueBoxTable)

// rename table
func renameTable(_ table: ValueBoxTable, to toTable: ValueBoxTable)

// remote the database and tables from disk also memory
func drop()

// count records with associated key in start ... end range
func count(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey) -> Int

// count all records in table
func count(_ table: ValueBoxTable) -> Int

// detach database which previous attached from exportBsePath
func exportEncrypted(to exportBasePath: String, encryptionParameters: ValueBoxEncryptionParameters)

ValueBoxTable

struct ValueBoxTable

1
2
3
let id: Int32
let keyType: ValueBoxKeyType
let compactValuesOnCreation: Bool

SqliteValueBoxTable

struct SqliteValueBoxTable

1
2
let table: ValueBoxTable
let hasPrimaryKey: Bool

SqliteValueBox

class SqliteValueBox:ValueBox

见另一篇

Table

class Table

1
2
3
4
5
6
7
8
public final let valueBox: ValueBox
public final let table: ValueBoxTable
public final let useCaches: Bool

open func clearMemoryCache() {
}
open func beforeCommit() {
}
This post is licensed under CC BY 4.0 by the author.