- Notifications
You must be signed in to change notification settings - Fork3
Expand file tree
/
Copy pathcharSet.js
More file actions
89 lines (75 loc) · 2.4 KB
/
charSet.js
File metadata and controls
89 lines (75 loc) · 2.4 KB
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
constBITS_PER_BYTE=8
const{
abs, ceil, floor, log2
}=Math
constgcd=(a,b)=>{
letla=a
letlb=b
while(lb!==0){
[la,lb]=[lb,la%lb]
}
returnabs(la)
}
constlcm=(a,b)=>(a/gcd(a,b))*b
constgenNdxFn=(bitsPerChar)=>{
// If BITS_PER_BYTEs is a multiple of bitsPerChar, we can slice off an integer number
// of chars per byte.
if(lcm(bitsPerChar,BITS_PER_BYTE)===BITS_PER_BYTE){
return(chunk,slice,bytes)=>{
constlShift=bitsPerChar
constrShift=BITS_PER_BYTE-bitsPerChar
return((bytes[chunk]<<(lShift*slice))&0xff)>>rShift
}
}
// Otherwise, while slicing off bits per char, we can possibly straddle two
// of bytes, so a more work is involved
constslicesPerChunk=lcm(bitsPerChar,BITS_PER_BYTE)/BITS_PER_BYTE
return(chunk,slice,bytes)=>{
constbNum=chunk*slicesPerChunk
constoffset=(slice*bitsPerChar)/BITS_PER_BYTE
constlOffset=floor(offset)
constrOffset=ceil(offset)
constrShift=BITS_PER_BYTE-bitsPerChar
constlShift=(slice*bitsPerChar)%BITS_PER_BYTE
letndx=((bytes[bNum+lOffset]<<lShift)&0xff)>>rShift
constr1Bits=(rOffset+1)*BITS_PER_BYTE
consts1Bits=(slice+1)*bitsPerChar
constrShiftIt=(r1Bits-s1Bits)%BITS_PER_BYTE
if(rShift<rShiftIt){
ndx+=bytes[bNum+rOffset]>>rShiftIt
}
returnndx
}
}
classCharSet{
constructor(chars){
if(!(typeofchars==='string'||charsinstanceofString)){
thrownewError('Invalid chars: Must be string')
}
const{ length}=chars
if(![2,4,8,16,32,64].includes(length)){
thrownewError('Invalid char count: must be one of 2,4,8,16,32,64')
}
// Ensure no repeated characters
for(leti=0;i<length;i+=1){
constc=chars.charAt(i)
for(letj=i+1;j<length;j+=1){
if(c===chars.charAt(j)){
thrownewError('Characters not unique')
}
}
}
this.chars=chars
this.bitsPerChar=floor(log2(length))
this.length=length
this.ndxFn=genNdxFn(this.bitsPerChar)
this.charsPerChunk=lcm(this.bitsPerChar,BITS_PER_BYTE)/this.bitsPerChar
}
bytesNeeded(bitLen){
constcount=ceil(bitLen/this.bitsPerChar)
returnceil((count*this.bitsPerChar)/BITS_PER_BYTE)
}
}
module.exports={
CharSet
}