AK-21/Graphite-Industrial-Intelligence
0
1'use strict'2 3const { Buffer } = require('buffer')4const symbol = Symbol.for('BufferList')5 6function BufferList (buf) {7 if (!(this instanceof BufferList)) {8 return new BufferList(buf)9 }10 11 BufferList._init.call(this, buf)12}13 14BufferList._init = function _init (buf) {15 Object.defineProperty(this, symbol, { value: true })16 17 this._bufs = []18 this.length = 019 20 if (buf) {21 this.append(buf)22 }23}24 25BufferList.prototype._new = function _new (buf) {26 return new BufferList(buf)27}28 29BufferList.prototype._offset = function _offset (offset) {30 if (offset === 0) {31 return [0, 0]32 }33 34 let tot = 035 36 for (let i = 0; i < this._bufs.length; i++) {37 const _t = tot + this._bufs[i].length38 if (offset < _t || i === this._bufs.length - 1) {39 return [i, offset - tot]40 }41 tot = _t42 }43}44 45BufferList.prototype._reverseOffset = function (blOffset) {46 const bufferId = blOffset[0]47 let offset = blOffset[1]48 49 for (let i = 0; i < bufferId; i++) {50 offset += this._bufs[i].length51 }52 53 return offset54}55 56BufferList.prototype.get = function get (index) {57 if (index > this.length || index < 0) {58 return undefined59 }60 61 const offset = this._offset(index)62 63 return this._bufs[offset[0]][offset[1]]64}65 66BufferList.prototype.slice = function slice (start, end) {67 if (typeof start === 'number' && start < 0) {68 start += this.length69 }70 71 if (typeof end === 'number' && end < 0) {72 end += this.length73 }74 75 return this.copy(null, 0, start, end)76}77 78BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {79 if (typeof srcStart !== 'number' || srcStart < 0) {80 srcStart = 081 }82 83 if (typeof srcEnd !== 'number' || srcEnd > this.length) {84 srcEnd = this.length85 }86 87 if (srcStart >= this.length) {88 return dst || Buffer.alloc(0)89 }90 91 if (srcEnd <= 0) {92 return dst || Buffer.alloc(0)93 }94 95 const copy = !!dst96 const off = this._offset(srcStart)97 const len = srcEnd - srcStart98 let bytes = len99 let bufoff = (copy && dstStart) || 0100 let start = off[1]101 102 // copy/slice everything103 if (srcStart === 0 && srcEnd === this.length) {104 if (!copy) {105 // slice, but full concat if multiple buffers106 return this._bufs.length === 1107 ? this._bufs[0]108 : Buffer.concat(this._bufs, this.length)109 }110 111 // copy, need to copy individual buffers112 for (let i = 0; i < this._bufs.length; i++) {113 this._bufs[i].copy(dst, bufoff)114 bufoff += this._bufs[i].length115 }116 117 return dst118 }119 120 // easy, cheap case where it's a subset of one of the buffers121 if (bytes <= this._bufs[off[0]].length - start) {122 return copy123 ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)124 : this._bufs[off[0]].slice(start, start + bytes)125 }126 127 if (!copy) {128 // a slice, we need something to copy in to129 dst = Buffer.allocUnsafe(len)130 }131 132 for (let i = off[0]; i < this._bufs.length; i++) {133 const l = this._bufs[i].length - start134 135 if (bytes > l) {136 this._bufs[i].copy(dst, bufoff, start)137 bufoff += l138 } else {139 this._bufs[i].copy(dst, bufoff, start, start + bytes)140 bufoff += l141 break142 }143 144 bytes -= l145 146 if (start) {147 start = 0148 }149 }150 151 // safeguard so that we don't return uninitialized memory152 if (dst.length > bufoff) return dst.slice(0, bufoff)153 154 return dst155}156 157BufferList.prototype.shallowSlice = function shallowSlice (start, end) {158 start = start || 0159 end = typeof end !== 'number' ? this.length : end160 161 if (start < 0) {162 start += this.length163 }164 165 if (end < 0) {166 end += this.length167 }168 169 if (start === end) {170 return this._new()171 }172 173 const startOffset = this._offset(start)174 const endOffset = this._offset(end)175 const buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1)176 177 if (endOffset[1] === 0) {178 buffers.pop()179 } else {180 buffers[buffers.length - 1] = buffers[buffers.length - 1].slice(0, endOffset[1])181 }182 183 if (startOffset[1] !== 0) {184 buffers[0] = buffers[0].slice(startOffset[1])185 }186 187 return this._new(buffers)188}189 190BufferList.prototype.toString = function toString (encoding, start, end) {191 return this.slice(start, end).toString(encoding)192}193 194BufferList.prototype.consume = function consume (bytes) {195 // first, normalize the argument, in accordance with how Buffer does it196 bytes = Math.trunc(bytes)197 // do nothing if not a positive number198 if (Number.isNaN(bytes) || bytes <= 0) return this199 200 while (this._bufs.length) {201 if (bytes >= this._bufs[0].length) {202 bytes -= this._bufs[0].length203 this.length -= this._bufs[0].length204 this._bufs.shift()205 } else {206 this._bufs[0] = this._bufs[0].slice(bytes)207 this.length -= bytes208 break209 }210 }211 212 return this213}214 215BufferList.prototype.duplicate = function duplicate () {216 const copy = this._new()217 218 for (let i = 0; i < this._bufs.length; i++) {219 copy.append(this._bufs[i])220 }221 222 return copy223}224 225BufferList.prototype.append = function append (buf) {226 if (buf == null) {227 return this228 }229 230 if (buf.buffer) {231 // append a view of the underlying ArrayBuffer232 this._appendBuffer(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength))233 } else if (Array.isArray(buf)) {234 for (let i = 0; i < buf.length; i++) {235 this.append(buf[i])236 }237 } else if (this._isBufferList(buf)) {238 // unwrap argument into individual BufferLists239 for (let i = 0; i < buf._bufs.length; i++) {240 this.append(buf._bufs[i])241 }242 } else {243 // coerce number arguments to strings, since Buffer(number) does244 // uninitialized memory allocation245 if (typeof buf === 'number') {246 buf = buf.toString()247 }248 249 this._appendBuffer(Buffer.from(buf))250 }251 252 return this253}254 255BufferList.prototype._appendBuffer = function appendBuffer (buf) {256 this._bufs.push(buf)257 this.length += buf.length258}259 260BufferList.prototype.indexOf = function (search, offset, encoding) {261 if (encoding === undefined && typeof offset === 'string') {262 encoding = offset263 offset = undefined264 }265 266 if (typeof search === 'function' || Array.isArray(search)) {267 throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.')268 } else if (typeof search === 'number') {269 search = Buffer.from([search])270 } else if (typeof search === 'string') {271 search = Buffer.from(search, encoding)272 } else if (this._isBufferList(search)) {273 search = search.slice()274 } else if (Array.isArray(search.buffer)) {275 search = Buffer.from(search.buffer, search.byteOffset, search.byteLength)276 } else if (!Buffer.isBuffer(search)) {277 search = Buffer.from(search)278 }279 280 offset = Number(offset || 0)281 282 if (isNaN(offset)) {283 offset = 0284 }285 286 if (offset < 0) {287 offset = this.length + offset288 }289 290 if (offset < 0) {291 offset = 0292 }293 294 if (search.length === 0) {295 return offset > this.length ? this.length : offset296 }297 298 const blOffset = this._offset(offset)299 let blIndex = blOffset[0] // index of which internal buffer we're working on300 let buffOffset = blOffset[1] // offset of the internal buffer we're working on301 302 // scan over each buffer303 for (; blIndex < this._bufs.length; blIndex++) {304 const buff = this._bufs[blIndex]305 306 while (buffOffset < buff.length) {307 const availableWindow = buff.length - buffOffset308 309 if (availableWindow >= search.length) {310 const nativeSearchResult = buff.indexOf(search, buffOffset)311 312 if (nativeSearchResult !== -1) {313 return this._reverseOffset([blIndex, nativeSearchResult])314 }315 316 buffOffset = buff.length - search.length + 1 // end of native search window317 } else {318 const revOffset = this._reverseOffset([blIndex, buffOffset])319 320 if (this._match(revOffset, search)) {321 return revOffset322 }323 324 buffOffset++325 }326 }327 328 buffOffset = 0329 }330 331 return -1332}333 334BufferList.prototype._match = function (offset, search) {335 if (this.length - offset < search.length) {336 return false337 }338 339 for (let searchOffset = 0; searchOffset < search.length; searchOffset++) {340 if (this.get(offset + searchOffset) !== search[searchOffset]) {341 return false342 }343 }344 return true345}346 347;(function () {348 const methods = {349 readDoubleBE: 8,350 readDoubleLE: 8,351 readFloatBE: 4,352 readFloatLE: 4,353 readInt32BE: 4,354 readInt32LE: 4,355 readUInt32BE: 4,356 readUInt32LE: 4,357 readInt16BE: 2,358 readInt16LE: 2,359 readUInt16BE: 2,360 readUInt16LE: 2,361 readInt8: 1,362 readUInt8: 1,363 readIntBE: null,364 readIntLE: null,365 readUIntBE: null,366 readUIntLE: null367 }368 369 for (const m in methods) {370 (function (m) {371 if (methods[m] === null) {372 BufferList.prototype[m] = function (offset, byteLength) {373 return this.slice(offset, offset + byteLength)[m](0, byteLength)374 }375 } else {376 BufferList.prototype[m] = function (offset = 0) {377 return this.slice(offset, offset + methods[m])[m](0)378 }379 }380 }(m))381 }382}())383 384// Used internally by the class and also as an indicator of this object being385// a `BufferList`. It's not possible to use `instanceof BufferList` in a browser386// environment because there could be multiple different copies of the387// BufferList class and some `BufferList`s might be `BufferList`s.388BufferList.prototype._isBufferList = function _isBufferList (b) {389 return b instanceof BufferList || BufferList.isBufferList(b)390}391 392BufferList.isBufferList = function isBufferList (b) {393 return b != null && b[symbol]394}395 396module.exports = BufferList397 