Passed
Push — master ( 8dff6d...8b723e )
by Rafael S.
01:23
created

src/bit-parser.js   B

Complexity

Total Complexity 43
Complexity/F 1.39

Size

Lines of Code 397
Function Count 31

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 0
wmc 43
c 2
b 1
f 0
nc 1
mnd 1
bc 37
fnc 31
dl 0
loc 397
rs 8.3157
bpm 1.1935
cpm 1.387
noi 0

31 Functions

Rating   Name   Duplication   Size   Complexity  
A BitReader.read40Bit 0 3 1
A BitReader.read32BitFloat 0 4 1
A BitWriter.write32Bit 0 5 1
A BitWriter.write24Bit 0 5 1
A BitReader.read32Bit 0 4 1
A BitReader.read24Bit 0 3 1
A BitReader.read64BitFloat 0 5 1
A BitReader.readChar 0 10 2
A BitReader.read16BitFloat 0 12 3
A BitWriter.write32BitFloat 0 5 1
A BitWriter.write8Bit 0 4 1
A BitWriter.write4Bit 0 4 1
A BitReader.read53Bit 0 3 1
A BitReader.read16Bit 0 3 1
A BitWriter.write48Bit 0 5 1
A BitWriter.write16BitFloat 0 14 2
A BitWriter.write64BitFloat 0 5 1
A BitWriter.write53Bit 0 5 1
A BitWriter.write16Bit 0 5 1
A BitReader.read48Bit 0 3 1
A BitWriter.write2Bit 0 4 2
A BitWriter.write40Bit 0 5 1
A BitReader.read8Bit 0 3 1
A bit-parser.js ➔ readBytesAsBits 0 10 2
A bit-parser.js ➔ getBinary 0 11 2
A BitWriter.write7Bit 0 4 2
A BitWriter.write6Bit 0 4 2
A BitWriter.write3Bit 0 4 2
A BitWriter.writeString 0 4 1
A BitWriter.write1Bit 0 4 2
A BitWriter.write5Bit 0 4 2

How to fix   Complexity   

Complexity

Complex classes like src/bit-parser.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * bit-parser: Functions to read and write bytes.
3
 * Copyright (c) 2017 Rafael da Silva Rocha.
4
 * https://github.com/rochars/byte-data
5
 * Floats based on int-bits: https://github.com/Jam3/int-bits
6
 * Future: fix https://github.com/majimboo/c-struct 40 and 48-bit
7
 */
8
9
/** @private */
10
let f32 = new Float32Array(1);
11
/** @private */
12
let i32 = new Int32Array(f32.buffer);
13
/** @private */
14
let f64 = new Float64Array(1);
15
/** @private */
16
let ui32 = new Uint32Array(f64.buffer);
17
18
/**
19
 * Functions to read data from bytes.
20
 * @enum {Function}
21
 */
22
const BitReader = {
23
24
    /**
25
     * Read 1 8-bit int from from bytes.
26
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
27
     * @param {number} i The index to read.
28
     * @return {number}
29
     */
30
    "read8Bit": function (bytes, i) {
31
        return bytes[i];
32
    },
33
34
    /**
35
     * Read 1 16-bit int from from bytes.
36
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
37
     * @param {number} i The index to read.
38
     * @return {number}
39
     */
40
    "read16Bit": function (bytes, i) {
41
        return bytes[1 + i] << 8 | bytes[i];
42
    },
43
44
    /**
45
     * Read 1 16-bit float from from bytes.
46
     * Thanks https://stackoverflow.com/a/8796597
47
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
48
     * @param {number} i The index to read.
49
     * @return {number}
50
     */
51
    "read16BitFloat": function (bytes, i) {
52
        let binary = parseInt(getBinary([bytes[i], bytes[i+1]]), 2);
53
        let exponent = (binary & 0x7C00) >> 10;
54
        let fraction = binary & 0x03FF;
55
        let floatValue;
56
        if (exponent) {
57
            floatValue =  Math.pow(2, exponent - 15) * (1 + fraction / 0x400);
58
        } else {
59
            floatValue = 6.103515625e-5 * (fraction / 0x400);
60
        }
61
        return  floatValue * (binary >> 15 ? -1 : 1);
62
    },
63
64
    /**
65
     * Read 1 24-bit int from from bytes.
66
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
67
     * @param {number} i The index to read.
68
     * @return {number}
69
     */
70
    "read24Bit": function (bytes, i) {
71
        return bytes[2 + i] << 16 | BitReader["read16Bit"](bytes, i);
72
    },
73
74
    /**
75
     * Read 1 32-bit int from from bytes.
76
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
77
     * @param {number} i The index to read.
78
     * @return {number}
79
     */
80
    "read32Bit": function (bytes, i) {
81
        return (bytes[3 + i] << 24 |
82
            BitReader["read24Bit"](bytes, i)) >>> 0;
83
    },
84
85
    /**
86
     * Read 1 32-bit float from from bytes.
87
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
88
     * @param {number} i The index to read.
89
     * @return {number}
90
     */
91
    "read32BitFloat": function (bytes, i) {
92
        i32[0] = BitReader["read32Bit"](bytes, i);
93
        return f32[0];
94
    },
95
96
    /**
97
     * Read 1 40-bit int from from bytes.
98
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
99
     * @param {number} i The index to read.
100
     * @return {number}
101
     */
102
    "read40Bit": function (bytes, i) {
103
        return readBytesAsBits(bytes, i, 5);
104
    },
105
106
    /**
107
     * Read 1 48-bit int from bytes.
108
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
109
     * @param {number} i The index to read.
110
     * @return {number}
111
     */
112
    "read48Bit": function (bytes, i) {
113
        return readBytesAsBits(bytes, i, 6);
114
    },
115
116
    /**
117
     * Read 1 53-bit int from bytes.
118
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
119
     * @param {number} i The index to read.
120
     * @return {number}
121
     */
122
    "read53Bit": function (bytes, i) {
123
        return readBytesAsBits(bytes, i, 7);
124
    },
125
126
    /**
127
     * Read 1 64-bit double from bytes.
128
     * Thanks https://gist.github.com/kg/2192799
129
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
130
     * @param {number} i The index to read.
131
     * @return {number}
132
     */
133
    "read64BitFloat": function (bytes, i) {
134
        ui32[0] = BitReader["read32Bit"](bytes, i);
135
        ui32[1] = BitReader["read32Bit"](bytes, i + 4);
136
        return f64[0];
137
    },
138
139
    /**
140
     * Read 1 char from bytes.
141
     * @param {!Array<number>|Uint8Array} bytes An array of bytes.
142
     * @param {number} i The index to read.
143
     * @param {Object} type The index to read.
144
     * @return {string}
145
     */
146
    "readChar": function (bytes, i, type) {
147
        let chrs = "";
148
        let j = 0;
149
        let len = type.bits / 8;
150
        while(j < len) {
151
            chrs += String.fromCharCode(bytes[i+j]);
152
            j++;
153
        }
154
        return chrs;
155
    }
156
};
157
158
/**
159
 * Functions to write data to bytes.
160
 * @enum {Function}
161
 */
162
let BitWriter = {
163
164
    /**
165
     * Write one 64-bit float as a binary value.
166
     * @param {!Array<number>} bytes An array of bytes.
167
     * @param {number} number The number to write as bytes.
168
     * @param {number} j The index being written in the byte buffer.
169
     * @return {number} The next index to write on the byte buffer.
170
     */
171
    "write64BitFloat": function(bytes, number, j) {
172
        f64[0] = number;
173
        j = BitWriter["write32Bit"](bytes, ui32[0], j);
174
        return BitWriter["write32Bit"](bytes, ui32[1], j);
175
    },
176
177
    /**
178
     * Write one 53-bit integer as a binary value.
179
     * @param {!Array<number>} bytes An array of bytes.
180
     * @param {number} number The number to write as bytes.
181
     * @param {number} j The index being written in the byte buffer.
182
     * @return {number} The next index to write on the byte buffer.
183
     */
184
    "write53Bit": function (bytes, number, j) {
185
        j = BitWriter["write48Bit"](bytes, number, j);
186
        bytes[j++] = Math.floor(number / Math.pow(2, 48)) & 0xFF;
187
        return j;
188
    },
189
190
    /**
191
     * Write one 48-bit integer as a binary value.
192
     * @param {!Array<number>} bytes An array of bytes.
193
     * @param {number} number The number to write as bytes.
194
     * @param {number} j The index being written in the byte buffer.
195
     * @return {number} The next index to write on the byte buffer.
196
     */
197
    "write48Bit": function (bytes, number, j) {
198
        j = BitWriter["write40Bit"](bytes, number, j);
199
        bytes[j++] = Math.floor(number / Math.pow(2, 40)) & 0xFF;
200
        return j;
201
    },
202
203
    /**
204
     * Write one 40-bit integer as a binary value.
205
     * @param {!Array<number>} bytes An array of bytes.
206
     * @param {number} number The number to write as bytes.
207
     * @param {number} j The index being written in the byte buffer.
208
     * @return {number} The next index to write on the byte buffer.
209
     */
210
    "write40Bit": function (bytes, number, j) {
211
        j = BitWriter["write32Bit"](bytes, number, j);
212
        bytes[j++] = Math.floor(number / Math.pow(2, 32)) & 0xFF;
213
        return j;
214
    },
215
216
    /**
217
     * Write one 32-bit float as a binary value.
218
     * @param {!Array<number>} bytes An array of bytes.
219
     * @param {number} number The number to write as bytes.
220
     * @param {number} j The index being written in the byte buffer.
221
     * @return {number} The next index to write on the byte buffer.
222
     */
223
    "write32BitFloat": function (bytes, number, j) {
224
        f32[0] = number;
225
        j = BitWriter["write32Bit"](bytes, i32[0], j);
226
        return j;
227
    },
228
229
    /**
230
     * Write one 32-bit integer as a binary value.
231
     * @param {!Array<number>} bytes An array of bytes.
232
     * @param {number} number The number to write as bytes.
233
     * @param {number} j The index being written in the byte buffer.
234
     * @return {number} The next index to write on the byte buffer.
235
     */
236
    "write32Bit": function (bytes, number, j) {
237
        j = BitWriter["write24Bit"](bytes, number, j);
238
        bytes[j++] = number >>> 24 & 0xFF;
239
        return j;
240
    },
241
242
    /**
243
     * Write one 24-bit integer as a binary value.
244
     * @param {!Array<number>} bytes An array of bytes.
245
     * @param {number} number The number to write as bytes.
246
     * @param {number} j The index being written in the byte buffer.
247
     * @return {number} The next index to write on the byte buffer.
248
     */
249
    "write24Bit": function (bytes, number, j) {
250
        j = BitWriter["write16Bit"](bytes, number, j);
251
        bytes[j++] = number >>> 16 & 0xFF;
252
        return j;
253
    },
254
255
    /**
256
     * Write one 16-bit integer as a binary value.
257
     * @param {!Array<number>} bytes An array of bytes.
258
     * @param {number} number The number to write as bytes.
259
     * @param {number} j The index being written in the byte buffer.
260
     * @return {number} The next index to write on the byte buffer.
261
     */
262
    "write16Bit": function (bytes, number, j) {
263
        bytes[j++] = number & 0xFF;
264
        bytes[j++] = number >>> 8 & 0xFF;
265
        return j;
266
    },
267
268
    /**
269
     * Write one 16-bit float as a binary value.
270
     * @param {!Array<number>} bytes An array of bytes.
271
     * @param {number} number The number to write as bytes.
272
     * @param {number} j The index being written in the byte buffer.
273
     * @return {number} The next index to write on the byte buffer.
274
     */
275
    "write16BitFloat": function (bytes, number, j) {
276
        f32[0] = number;
277
        let x = i32[0];
278
        let bits = (x >> 16) & 0x8000;
279
        let m = (x >> 12) & 0x07ff;
280
        let e = (x >> 23) & 0xff;
281
        if (e >= 103) {
282
            bits |= ((e - 112) << 10) | (m >> 1);
283
            bits += m & 1;
284
        }
285
        bytes[j] = bits & 0xFF;
286
        bytes[j+1] = bits >>> 8 & 0xFF;
287
        return j+2;
288
    },
289
290
    /**
291
     * Write one 8-bit integer as a binary value.
292
     * @param {!Array<number>} bytes An array of bytes.
293
     * @param {number} number The number to write as bytes.
294
     * @param {number} j The index being written in the byte buffer.
295
     * @return {number} The next index to write on the byte buffer.
296
     */
297
    "write8Bit": function (bytes, number, j) {
298
        bytes[j++] = number & 0xFF;
299
        return j;
300
    },
301
302
    /**
303
     * Write one 4-bit integer as a binary value.
304
     * @param {!Array<number>} bytes An array of bytes.
305
     * @param {number} number The number to write as bytes.
306
     * @param {number} j The index being written in the byte buffer.
307
     * @return {number} The next index to write on the byte buffer.
308
     */
309
    "write4Bit": function (bytes, number, j) {
310
        bytes[j++] = number & 0xF;
311
        return j;
312
    },
313
314
    /**
315
     * Write one 2-bit integer as a binary value.
316
     * @param {!Array<number>} bytes An array of bytes.
317
     * @param {number} number The number to write as bytes.
318
     * @param {number} j The index being written in the byte buffer.
319
     * @return {number} The next index to write on the byte buffer.
320
     */
321
    "write2Bit": function (bytes, number, j) {
322
        bytes[j++] = number < 0 ? number + 4 : number;
323
        return j;
324
    },
325
326
    // 3-bit to 7-bit still need specific methods
327
    "write3Bit": function (bytes, number, j) {
328
        bytes[j++] = number < 0 ? number + Math.pow(2, 3) : number;
329
        return j;
330
    },
331
    "write5Bit": function (bytes, number, j) {
332
        bytes[j++] = number < 0 ? number + Math.pow(2, 5) : number;
333
        return j;
334
    },
335
    "write6Bit": function (bytes, number, j) {
336
        bytes[j++] = number < 0 ? number + Math.pow(2, 6) : number;
337
        return j;
338
    },
339
    "write7Bit": function (bytes, number, j) {
340
        bytes[j++] = number < 0 ? number + Math.pow(2, 7) : number;
341
        return j;
342
    },
343
344
    /**
345
     * Write one boolean as a binary value.
346
     * @param {!Array<number>} bytes An array of bytes.
347
     * @param {number} number The number to write as bytes.
348
     * @param {number} j The index being written in the byte buffer.
349
     * @return {number} The next index to write on the byte buffer.
350
     */
351
    "write1Bit": function (bytes, number, j) {
352
        bytes[j++] = number ? 1 : 0;
353
        return j;
354
    },
355
356
    /**
357
     * Write one char as a byte.
358
     * @param {!Array<number>} bytes An array of bytes.
359
     * @param {string} string The string to write as bytes.
360
     * @param {number} j The index being written in the byte buffer.
361
     * @return {number} The next index to write on the byte buffer.
362
     */
363
    "writeString": function (bytes, string, j) {
364
        bytes[j++] = string.charCodeAt(0);
365
        return j;
366
    }
367
};
368
369
/**
370
 * Get a binary string representation of a value described as bytes.
371
 * @param {Array<number>|number} bytes The bytes.
372
 * @return {string}
373
 */
374
function getBinary(bytes) {
375
    let binary = "";
376
    let i = 0;
377
    let bytesLength = bytes.length;
378
    while(i < bytesLength) {
379
        let bits = bytes[i].toString(2);
380
        binary = Array(9 - bits.length).join("0") + bits + binary;
381
        i++;
382
    }
383
    return binary;
384
}
385
386
/**
387
 * Read a group of bytes by turning it to bits.
388
 * @param {!Array<number>|Uint8Array} bytes An array of bytes.
389
 * @param {number} i The index to read.
390
 * @param {number} numBytes The number of bytes
391
 *      (1 for 8-bit, 2 for 16-bit, etc).
392
 * @return {number}
393
 */
394
function readBytesAsBits(bytes, i, numBytes) {
395
    let j = numBytes-1;
396
    let byte = "";
397
    while (j >= 0) {
398
        let bits = bytes[j + i].toString(2);
399
        byte += Array(9 - bits.length).join("0") + bits;
400
        j--;
401
    }
402
    return parseInt(byte, 2);
403
}
404
405
exports.BitWriter = BitWriter;
406
exports.BitReader = BitReader;
407