UNPKG

@sskmy1024y/react-native-hash

Version:
134 lines (116 loc) 3.46 kB
/* eslint linebreak-style: ["error", "windows"] */ /* eslint-disable no-use-before-define */ import Base from './Base.js'; import WordArray from './WordArray.js'; import Utf8 from './Utf8.js'; /** * Abstract buffered block algorithm template. * * The property blockSize must be implemented in a concrete subtype. * * @property {number} _minBufferSize * * The number of blocks that should be kept unprocessed in the buffer. Default: 0 */ export default class BufferedBlockAlgorithm extends Base { constructor() { super(); this._minBufferSize = 0; } /** * Resets this block algorithm's data buffer to its initial state. * * @example * * bufferedBlockAlgorithm.reset(); */ reset() { // Initial values this._data = new WordArray(); this._nDataBytes = 0; } /** * Adds new data to this block algorithm's buffer. * * @param {WordArray|string} data * * The data to append. Strings are converted to a WordArray using UTF-8. * * @example * * bufferedBlockAlgorithm._append('data'); * bufferedBlockAlgorithm._append(wordArray); */ _append(data) { let m_data = data; // Convert string to WordArray, else assume WordArray already if (typeof m_data === 'string') { m_data = Utf8.parse(m_data); } // Append this._data.concat(m_data); this._nDataBytes += m_data.sigBytes; } /** * 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 {WordArray} The processed data. * * @example * * var processedData = bufferedBlockAlgorithm._process(); * var processedData = bufferedBlockAlgorithm._process(!!'flush'); */ _process(doFlush) { let processedWords; // Shortcuts const { _data: data, blockSize } = this; const dataWords = data.words; const dataSigBytes = data.sigBytes; const blockSizeBytes = blockSize * 4; // Count blocks ready let nBlocksReady = dataSigBytes / blockSizeBytes; if (doFlush) { // Round up to include partial blocks nBlocksReady = Math.ceil(nBlocksReady); } else { // Round down to include only full blocks, // less the number of blocks that must remain in the buffer nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); } // Count words ready const nWordsReady = nBlocksReady * blockSize; // Count bytes ready const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks if (nWordsReady) { for (let offset = 0; offset < nWordsReady; offset += blockSize) { // Perform concrete-algorithm logic this._doProcessBlock(dataWords, offset); } // Remove processed words processedWords = dataWords.splice(0, nWordsReady); data.sigBytes -= nBytesReady; } // Return processed words return new WordArray(processedWords, nBytesReady); } /** * Creates a copy of this object. * * @return {Object} The clone. * * @example * * var clone = bufferedBlockAlgorithm.clone(); */ clone() { const clone = super.clone.call(this); clone._data = this._data.clone(); return clone; } }