11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  StringPrototypeSlice,
51cb0ef41Sopenharmony_ci  SymbolIterator,
61cb0ef41Sopenharmony_ci  TypedArrayPrototypeSet,
71cb0ef41Sopenharmony_ci  Uint8Array,
81cb0ef41Sopenharmony_ci} = primordials;
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
111cb0ef41Sopenharmony_ciconst { inspect } = require('internal/util/inspect');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cimodule.exports = class BufferList {
141cb0ef41Sopenharmony_ci  constructor() {
151cb0ef41Sopenharmony_ci    this.head = null;
161cb0ef41Sopenharmony_ci    this.tail = null;
171cb0ef41Sopenharmony_ci    this.length = 0;
181cb0ef41Sopenharmony_ci  }
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci  push(v) {
211cb0ef41Sopenharmony_ci    const entry = { data: v, next: null };
221cb0ef41Sopenharmony_ci    if (this.length > 0)
231cb0ef41Sopenharmony_ci      this.tail.next = entry;
241cb0ef41Sopenharmony_ci    else
251cb0ef41Sopenharmony_ci      this.head = entry;
261cb0ef41Sopenharmony_ci    this.tail = entry;
271cb0ef41Sopenharmony_ci    ++this.length;
281cb0ef41Sopenharmony_ci  }
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  unshift(v) {
311cb0ef41Sopenharmony_ci    const entry = { data: v, next: this.head };
321cb0ef41Sopenharmony_ci    if (this.length === 0)
331cb0ef41Sopenharmony_ci      this.tail = entry;
341cb0ef41Sopenharmony_ci    this.head = entry;
351cb0ef41Sopenharmony_ci    ++this.length;
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  shift() {
391cb0ef41Sopenharmony_ci    if (this.length === 0)
401cb0ef41Sopenharmony_ci      return;
411cb0ef41Sopenharmony_ci    const ret = this.head.data;
421cb0ef41Sopenharmony_ci    if (this.length === 1)
431cb0ef41Sopenharmony_ci      this.head = this.tail = null;
441cb0ef41Sopenharmony_ci    else
451cb0ef41Sopenharmony_ci      this.head = this.head.next;
461cb0ef41Sopenharmony_ci    --this.length;
471cb0ef41Sopenharmony_ci    return ret;
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  clear() {
511cb0ef41Sopenharmony_ci    this.head = this.tail = null;
521cb0ef41Sopenharmony_ci    this.length = 0;
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  join(s) {
561cb0ef41Sopenharmony_ci    if (this.length === 0)
571cb0ef41Sopenharmony_ci      return '';
581cb0ef41Sopenharmony_ci    let p = this.head;
591cb0ef41Sopenharmony_ci    let ret = '' + p.data;
601cb0ef41Sopenharmony_ci    while ((p = p.next) !== null)
611cb0ef41Sopenharmony_ci      ret += s + p.data;
621cb0ef41Sopenharmony_ci    return ret;
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  concat(n) {
661cb0ef41Sopenharmony_ci    if (this.length === 0)
671cb0ef41Sopenharmony_ci      return Buffer.alloc(0);
681cb0ef41Sopenharmony_ci    const ret = Buffer.allocUnsafe(n >>> 0);
691cb0ef41Sopenharmony_ci    let p = this.head;
701cb0ef41Sopenharmony_ci    let i = 0;
711cb0ef41Sopenharmony_ci    while (p) {
721cb0ef41Sopenharmony_ci      TypedArrayPrototypeSet(ret, p.data, i);
731cb0ef41Sopenharmony_ci      i += p.data.length;
741cb0ef41Sopenharmony_ci      p = p.next;
751cb0ef41Sopenharmony_ci    }
761cb0ef41Sopenharmony_ci    return ret;
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Consumes a specified amount of bytes or characters from the buffered data.
801cb0ef41Sopenharmony_ci  consume(n, hasStrings) {
811cb0ef41Sopenharmony_ci    const data = this.head.data;
821cb0ef41Sopenharmony_ci    if (n < data.length) {
831cb0ef41Sopenharmony_ci      // `slice` is the same for buffers and strings.
841cb0ef41Sopenharmony_ci      const slice = data.slice(0, n);
851cb0ef41Sopenharmony_ci      this.head.data = data.slice(n);
861cb0ef41Sopenharmony_ci      return slice;
871cb0ef41Sopenharmony_ci    }
881cb0ef41Sopenharmony_ci    if (n === data.length) {
891cb0ef41Sopenharmony_ci      // First chunk is a perfect match.
901cb0ef41Sopenharmony_ci      return this.shift();
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci    // Result spans more than one buffer.
931cb0ef41Sopenharmony_ci    return hasStrings ? this._getString(n) : this._getBuffer(n);
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  first() {
971cb0ef41Sopenharmony_ci    return this.head.data;
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  *[SymbolIterator]() {
1011cb0ef41Sopenharmony_ci    for (let p = this.head; p; p = p.next) {
1021cb0ef41Sopenharmony_ci      yield p.data;
1031cb0ef41Sopenharmony_ci    }
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  // Consumes a specified amount of characters from the buffered data.
1071cb0ef41Sopenharmony_ci  _getString(n) {
1081cb0ef41Sopenharmony_ci    let ret = '';
1091cb0ef41Sopenharmony_ci    let p = this.head;
1101cb0ef41Sopenharmony_ci    let c = 0;
1111cb0ef41Sopenharmony_ci    do {
1121cb0ef41Sopenharmony_ci      const str = p.data;
1131cb0ef41Sopenharmony_ci      if (n > str.length) {
1141cb0ef41Sopenharmony_ci        ret += str;
1151cb0ef41Sopenharmony_ci        n -= str.length;
1161cb0ef41Sopenharmony_ci      } else {
1171cb0ef41Sopenharmony_ci        if (n === str.length) {
1181cb0ef41Sopenharmony_ci          ret += str;
1191cb0ef41Sopenharmony_ci          ++c;
1201cb0ef41Sopenharmony_ci          if (p.next)
1211cb0ef41Sopenharmony_ci            this.head = p.next;
1221cb0ef41Sopenharmony_ci          else
1231cb0ef41Sopenharmony_ci            this.head = this.tail = null;
1241cb0ef41Sopenharmony_ci        } else {
1251cb0ef41Sopenharmony_ci          ret += StringPrototypeSlice(str, 0, n);
1261cb0ef41Sopenharmony_ci          this.head = p;
1271cb0ef41Sopenharmony_ci          p.data = StringPrototypeSlice(str, n);
1281cb0ef41Sopenharmony_ci        }
1291cb0ef41Sopenharmony_ci        break;
1301cb0ef41Sopenharmony_ci      }
1311cb0ef41Sopenharmony_ci      ++c;
1321cb0ef41Sopenharmony_ci    } while ((p = p.next) !== null);
1331cb0ef41Sopenharmony_ci    this.length -= c;
1341cb0ef41Sopenharmony_ci    return ret;
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  // Consumes a specified amount of bytes from the buffered data.
1381cb0ef41Sopenharmony_ci  _getBuffer(n) {
1391cb0ef41Sopenharmony_ci    const ret = Buffer.allocUnsafe(n);
1401cb0ef41Sopenharmony_ci    const retLen = n;
1411cb0ef41Sopenharmony_ci    let p = this.head;
1421cb0ef41Sopenharmony_ci    let c = 0;
1431cb0ef41Sopenharmony_ci    do {
1441cb0ef41Sopenharmony_ci      const buf = p.data;
1451cb0ef41Sopenharmony_ci      if (n > buf.length) {
1461cb0ef41Sopenharmony_ci        TypedArrayPrototypeSet(ret, buf, retLen - n);
1471cb0ef41Sopenharmony_ci        n -= buf.length;
1481cb0ef41Sopenharmony_ci      } else {
1491cb0ef41Sopenharmony_ci        if (n === buf.length) {
1501cb0ef41Sopenharmony_ci          TypedArrayPrototypeSet(ret, buf, retLen - n);
1511cb0ef41Sopenharmony_ci          ++c;
1521cb0ef41Sopenharmony_ci          if (p.next)
1531cb0ef41Sopenharmony_ci            this.head = p.next;
1541cb0ef41Sopenharmony_ci          else
1551cb0ef41Sopenharmony_ci            this.head = this.tail = null;
1561cb0ef41Sopenharmony_ci        } else {
1571cb0ef41Sopenharmony_ci          TypedArrayPrototypeSet(ret,
1581cb0ef41Sopenharmony_ci                                 new Uint8Array(buf.buffer, buf.byteOffset, n),
1591cb0ef41Sopenharmony_ci                                 retLen - n);
1601cb0ef41Sopenharmony_ci          this.head = p;
1611cb0ef41Sopenharmony_ci          p.data = buf.slice(n);
1621cb0ef41Sopenharmony_ci        }
1631cb0ef41Sopenharmony_ci        break;
1641cb0ef41Sopenharmony_ci      }
1651cb0ef41Sopenharmony_ci      ++c;
1661cb0ef41Sopenharmony_ci    } while ((p = p.next) !== null);
1671cb0ef41Sopenharmony_ci    this.length -= c;
1681cb0ef41Sopenharmony_ci    return ret;
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  // Make sure the linked list only shows the minimal necessary information.
1721cb0ef41Sopenharmony_ci  [inspect.custom](_, options) {
1731cb0ef41Sopenharmony_ci    return inspect(this, {
1741cb0ef41Sopenharmony_ci      ...options,
1751cb0ef41Sopenharmony_ci      // Only inspect one level.
1761cb0ef41Sopenharmony_ci      depth: 0,
1771cb0ef41Sopenharmony_ci      // It should not recurse.
1781cb0ef41Sopenharmony_ci      customInspect: false,
1791cb0ef41Sopenharmony_ci    });
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci};
182