-
Notifications
You must be signed in to change notification settings - Fork 0
/
hashtable.js
93 lines (89 loc) · 2.46 KB
/
hashtable.js
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
var HEADER = 8 //latest seq, count
var SEQ = 0
var COUNT = 4
function assertKey(key) {
if(!Number.isInteger(key) && key != 0) throw new Error('key must be integer, was:'+key)
}
function getSlot(key, slots) {
return HEADER + (key%slots) * 8
}
function insert(buffer, slots, key, value) {
value = value | 0
var i = key
do {
var slot = getSlot(i, slots)
var _key = buffer.readUInt32LE(slot)
var ptr = buffer.readUInt32LE(slot + 4)
//append to vector already stored
if(key === _key || _key == 0) {
if(_key == 0) {
buffer.writeUInt32LE(buffer.readUInt32LE(COUNT) + 1, COUNT)
buffer.writeUInt32LE(key, slot)
}
buffer.writeUInt32LE(value, slot+4)
return slot
}
else
i++
} while(true)
}
module.exports = function (buffer) {
var slots, count, self
if(buffer) {
slots = ~~((buffer.length - HEADER) / 8)
count = buffer.readUInt32LE(COUNT)
}
return self = {
initialize: function (_buffer) {
if(Buffer.isBuffer(_buffer)) {
slots = ~~((_buffer.length - HEADER) / 8)
count = _buffer.readUInt32LE(COUNT)
buffer = _buffer
}
else if('number' === typeof _buffer) {
slots = _buffer; count = 0
buffer = Buffer.alloc(HEADER + slots*8)
}
self.buffer = buffer
return self
},
set: function (key, value) {
assertKey(key)
return insert(buffer, slots, key, value)
},
update: function (slot, value, key) {
if(key != undefined && buffer.readUInt32LE(slot) !== key)
throw new Error('tried to update incorrect slot')
buffer.writeUInt32LE(value, slot + 4)
},
get: function (key) {
assertKey(key)
var i = key
do {
var slot = getSlot(i, slots)
var _key = buffer.readUInt32LE(slot)
if(_key == 0) return 0
else if(_key === key) return buffer.readUInt32LE(slot + 4)
else slot = (++ i % slots) * 8
} while(true)
},
rehash: function (slots2) {
slots2 = slots2 || slots*2
var _buffer = Buffer.alloc(HEADER + slots2*8)
for(var i = 0; i < slots; i++) {
var key = buffer.readUInt32LE(HEADER + i*8)
if(key) {
var value = buffer.readUInt32LE(HEADER + i*8 + 4)
insert(_buffer, slots2, key ,value)
}
}
self.buffer = buffer = _buffer
slots = slots2
return self
},
load: function () {
return buffer.readUInt32LE(COUNT) / slots
},
buffer: buffer
}
}