Buckets:
| /* | |
| Copyright (c) 2014-2021, Matteo Collina <hello@matteocollina.com> | |
| Permission to use, copy, modify, and/or distribute this software for any | |
| purpose with or without fee is hereby granted, provided that the above | |
| copyright notice and this permission notice appear in all copies. | |
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR | |
| IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| */ | |
| const { Transform } = require('stream') | |
| const { StringDecoder } = require('string_decoder') | |
| const kLast = Symbol('last') | |
| const kDecoder = Symbol('decoder') | |
| function transform (chunk, enc, cb) { | |
| let list | |
| if (this.overflow) { // Line buffer is full. Skip to start of next line. | |
| const buf = this[kDecoder].write(chunk) | |
| list = buf.split(this.matcher) | |
| if (list.length === 1) return cb() // Line ending not found. Discard entire chunk. | |
| // Line ending found. Discard trailing fragment of previous line and reset overflow state. | |
| list.shift() | |
| this.overflow = false | |
| } else { | |
| this[kLast] += this[kDecoder].write(chunk) | |
| list = this[kLast].split(this.matcher) | |
| } | |
| this[kLast] = list.pop() | |
| for (let i = 0; i < list.length; i++) { | |
| try { | |
| push(this, this.mapper(list[i])) | |
| } catch (error) { | |
| return cb(error) | |
| } | |
| } | |
| this.overflow = this[kLast].length > this.maxLength | |
| if (this.overflow && !this.skipOverflow) { | |
| cb(new Error('maximum buffer reached')) | |
| return | |
| } | |
| cb() | |
| } | |
| function flush (cb) { | |
| // forward any gibberish left in there | |
| this[kLast] += this[kDecoder].end() | |
| if (this[kLast]) { | |
| try { | |
| push(this, this.mapper(this[kLast])) | |
| } catch (error) { | |
| return cb(error) | |
| } | |
| } | |
| cb() | |
| } | |
| function push (self, val) { | |
| if (val !== undefined) { | |
| self.push(val) | |
| } | |
| } | |
| function noop (incoming) { | |
| return incoming | |
| } | |
| function split (matcher, mapper, options) { | |
| // Set defaults for any arguments not supplied. | |
| matcher = matcher || /\r?\n/ | |
| mapper = mapper || noop | |
| options = options || {} | |
| // Test arguments explicitly. | |
| switch (arguments.length) { | |
| case 1: | |
| // If mapper is only argument. | |
| if (typeof matcher === 'function') { | |
| mapper = matcher | |
| matcher = /\r?\n/ | |
| // If options is only argument. | |
| } else if (typeof matcher === 'object' && !(matcher instanceof RegExp) && !matcher[Symbol.split]) { | |
| options = matcher | |
| matcher = /\r?\n/ | |
| } | |
| break | |
| case 2: | |
| // If mapper and options are arguments. | |
| if (typeof matcher === 'function') { | |
| options = mapper | |
| mapper = matcher | |
| matcher = /\r?\n/ | |
| // If matcher and options are arguments. | |
| } else if (typeof mapper === 'object') { | |
| options = mapper | |
| mapper = noop | |
| } | |
| } | |
| options = Object.assign({}, options) | |
| options.autoDestroy = true | |
| options.transform = transform | |
| options.flush = flush | |
| options.readableObjectMode = true | |
| const stream = new Transform(options) | |
| stream[kLast] = '' | |
| stream[kDecoder] = new StringDecoder('utf8') | |
| stream.matcher = matcher | |
| stream.mapper = mapper | |
| stream.maxLength = options.maxLength | |
| stream.skipOverflow = options.skipOverflow || false | |
| stream.overflow = false | |
| stream._destroy = function (err, cb) { | |
| // Weird Node v12 bug that we need to work around | |
| this._writableState.errorEmitted = false | |
| cb(err) | |
| } | |
| return stream | |
| } | |
| module.exports = split | |
Xet Storage Details
- Size:
- 3.76 kB
- Xet hash:
- 8f150be6db2406ab373e3b721c314e420acc47beb5c95dd048b3a58756ce6c19
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.