/*
* This file is ported from
*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*/
/**
* @tsplus type ListBuffer
* @tsplus companion ListBuffer.Ops
*/
export class ListBuffer implements Collection, Equals {
private first: List = List.nil()
private last0: List.Cons | undefined = undefined
private len = 0;
[Symbol.iterator](): Iterator {
return this.first[Symbol.iterator]()
}
[Hash.sym]() {
return Hash.randomCached(this)
}
[Equals.sym](that: unknown) {
return this === that
}
static empty(): ListBuffer {
return new ListBuffer()
}
static from(as: Collection): ListBuffer {
const buf = new ListBuffer()
for (const a of as) {
buf.append(a)
}
return buf
}
get length(): number {
return this.len
}
get isEmpty(): boolean {
return this.len === 0
}
get unsafeHead(): A | undefined {
if (this.isEmpty) {
return undefined
}
return (this.first as List.Cons).head
}
get unsafeTail(): List | undefined {
if (this.isEmpty) {
return undefined
}
return (this.first as List.Cons).tail
}
append(this: this, elem: A): this {
const last1 = List.cons(elem, List.nil())
if (this.len === 0) {
this.first = last1
} else {
this.last0!.tail = last1
}
this.last0 = last1
this.len += 1
return this
}
prepend(this: this, elem: A): this {
this.insert(0, elem)
return this
}
unprepend(this: this): A {
if (this.isEmpty) {
throw new NoSuchElement()
}
const h = (this.first as List.Cons).head
this.first = (this.first as List.Cons).tail
this.len -= 1
return h
}
get toList(): List {
return this.first
}
insert(this: this, idx: number, elem: A): this {
if (idx < 0 || idx > this.len) {
throw new IndexOutOfBounds(idx, 0, this.len - 1)
}
if (idx === this.len) {
this.append(elem)
} else {
const p = this.locate(idx)
const nx = List.cons(elem, this.getNext(p))
if (p === undefined) {
this.first = nx
} else {
;(p as List.Cons).tail = nx
}
this.len += 1
}
return this
}
reduce(this: this, b: B, f: (b: B, a: A) => B): B {
return this.first.reduce(b, f)
}
private getNext(p: List | undefined): List {
if (p === undefined) {
return this.first
} else {
return p.unsafeTail!
}
}
private locate(i: number): List | undefined {
if (i === 0) {
return undefined
} else if (i === this.len) {
return this.last0
} else {
let p = this.first
for (let j = i - 1; j > 0; j--) {
p = p.unsafeTail!
}
return p
}
}
}
/**
* @tsplus getter ListBuffer toCollection
*/
export function toCollection(self: ListBuffer): Collection {
return self
}