BufferedBlockAlgorithm.js
3.1 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
import { Word32Array } from "../Word32Array";
import { Utf8 } from "../encoder/Utf8";
export class BufferedBlockAlgorithm {
constructor(props) {
this._minBufferSize = 0;
this._blockSize = 0;
this._props = props;
this._data = props && typeof props.data !== "undefined" ? props.data.clone() : new Word32Array();
this._nBytes = props && typeof props.nBytes === "number" ? props.nBytes : 0;
}
get blockSize() {
return this._blockSize;
}
/**
* Resets this block algorithm's data buffer to its initial state.
*
* @example
* bufferedBlockAlgorithm.reset();
*/
reset(data, nBytes) {
this._data = typeof data !== "undefined" ? data.clone() : new Word32Array();
this._nBytes = typeof nBytes === "number" ? nBytes : 0;
}
/**
* Adds new data to this block algorithm's buffer.
*
* @param {Word32Array|string} data The data to append. Strings are converted to a WordArray using UTF-8.
* @example
* bufferedBlockAlgorithm.append('data');
* bufferedBlockAlgorithm.append(wordArray);
*/
_append(data) {
const d = typeof data === "string" ? Utf8.parse(data) : data;
this._data.concat(d);
this._nBytes += d.nSigBytes;
}
/**
* Processes available data blocks.
* This method invokes doProcessBlock(offset), which must be implemented by a concrete subtype.
*
* @param {boolean?} doFlush Whether all blocks and partial blocks should be processed.
* @return {Word32Array} The processed data.
* @example
* var processedData = bufferedBlockAlgorithm.process();
* var processedData = bufferedBlockAlgorithm.process(!!'flush');
*/
_process(doFlush) {
let processedWords;
const words = this._data.words;
const nSigBytes = this._data.nSigBytes;
const blockSize = this._blockSize;
const blockSizeByte = this._blockSize * 4;
let nBlocksReady = nSigBytes / blockSizeByte;
if (doFlush) {
// Round up to include partial blocks
nBlocksReady = Math.ceil(nBlocksReady);
}
else {
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
// Count words ready
const nWordsReady = nBlocksReady * blockSize;
// Count bytes ready
const nBytesReady = Math.min(nWordsReady * 4, nSigBytes);
// Process blocks
if (nWordsReady) {
for (let offset = 0; offset < nWordsReady; offset += blockSize) {
// Perform concrete-algorithm logic
this._doProcessBlock(words, offset);
}
// Remove processed words
processedWords = words.splice(0, nWordsReady);
this._data.nSigBytes -= nBytesReady;
}
// Return processed words
return new Word32Array(processedWords, nBytesReady);
}
/**
* @abstract
*/
_doProcessBlock(words, offset) {
throw new Error("Not implemented");
}
}