-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
98 lines (86 loc) · 2.76 KB
/
index.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
94
95
96
97
98
'use strict'
const escapeStringRegexp = require('escape-string-regexp')
const crypto = require('crypto')
class Compressor {
constructor(opts) {
this.keySetLimit = opts && opts.keySetLimit? opts.keySetLimit: 500
this.keySetBook = {}
this.inProgressKeySet = {}
}
mergeKeySets(a, b) {
Object.keys(b).forEach((k) => a[k] = !!a[k] ? a[k] + b[k] : b[k])
return a
}
findKey(toCompress) {
const key = {}
let keyArray = Object.keys(this.inProgressKeySet).map((i) => [i, this.inProgressKeySet[i]])
const keySet = {}
JSON.stringify(toCompress)
.match(new RegExp('(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*")|true|false)', 'g'))
.sort((a, b) => b.length - a.length)
.forEach((i) => key[i] = (key[i] || 0) + 1)
Object.keys(key).forEach((a) => {
if(a.length > 4) {
let found = false
keyArray = keyArray.map((i) => {
if(i[0] === a) {
found = true
return [i[0], i[1] + (key[a] * a.length)]
}
return i
})
if(!found) {
keyArray.push([a, key[a] * a.length])
}
}
})
keyArray
.sort((a, b) => b[1] - a[1])
.slice(0, this.keySetLimit)
.map((a) => keySet[a[0]] = a[1])
this.inProgressKeySet = keySet
}
_setDicRegex(codeBook) {
codeBook.codeBookRegex = new RegExp(Object.keys(codeBook.dic).map((k) => escapeStringRegexp(k)).join('|'), 'g'),
codeBook.revCodeBookRegex = new RegExp(Object.keys(codeBook.revDic).map((k)=>escapeStringRegexp(k)).join('|'), 'g')
}
createKeySet() {
const revision = crypto.randomBytes(10)
const dictionary = {}
const reverseDictionary = {}
let pC = 10
Object.keys(this.inProgressKeySet).forEach((k) => {
const rand = String.fromCharCode(31) + String.fromCharCode(pC)
pC += 1
dictionary[k] = rand
reverseDictionary[rand] = k
})
this.keySetBook[revision] = {
dic: dictionary,
revDic: reverseDictionary,
}
this._setDicRegex(this.keySetBook[revision])
return revision
}
encode(obj, revision) {
const codeBook = this.keySetBook[revision].dic
return JSON.stringify(obj).toString()
.replace(this.keySetBook[revision].codeBookRegex, (m) => codeBook[m])
}
decode(str, revision) {
const codeBook = this.keySetBook[revision].revDic
return JSON.parse(str.toString().replace(this.keySetBook[revision].revCodeBookRegex, (m) => codeBook[m]))
}
getCodeBook(revision) {
return this.keySetBook[revision].dic
}
setCodeBook(revision, dic) {
this.keySetBook[revision] = {
dic: dic,
revDic: {},
}
Object.keys(dic).forEach((i) => this.keySetBook[revision].revDic[this.keySetBook[revision].dic[i]] = i)
this._setDicRegex(this.keySetBook[revision])
}
}
module.exports = Compressor