Files
iterables-js/src/List.js

145 lines
2.5 KiB
JavaScript

import { SequenceContainer } from "./containers/Sequence"
import { BidirectionalIterator } from "./iterators/Bidirectional"
import { mixinClasses } from "./utils/mixin"
export class List {
constructor(...args) {
this._end = new ListIterator(new ListItem())
this._begin = this._end
this._size = 0
if (args.length >= 1) {
this.assign(...args)
}
}
move(rhs) {
this._begin = rhs._begin
this._end = rhs._end
this._size = rhs._size
rhs._begin = undefined
rhs._end = undefined
rhs._size = 0
return this
}
size() {
return this._size
}
begin() {
return this._begin.clone()
}
end() {
return this._end.clone()
}
resize(size, value) {
if (this._size > size)
while (this._size !== size)
this.popBack()
else
while (this._size !== size)
this.pushBack(value)
}
_shiftRight(dest, generator) {
let prev, res, new_item, item = dest.deref()
for (const value of generator) {
prev = item._prev
new_item = new ListItem(value)
res = res ?? new_item
item._prev = new_item
new_item._next = item
new_item._prev = prev
if (prev) {
prev._next = new_item
} else {
this._begin = new ListIterator(res)
}
this._size++
}
return new ListIterator(res ?? dest.deref())
}
_shiftLeft(dest, generator) {
let item = dest.deref(), start_item = item
for (const _ of generator) {
item = item._prev
this._size--
}
if (item._prev) {
item._prev._next = start_item
} else {
this._begin = new ListIterator(start_item)
}
start_item._prev = item._prev
return dest
}
}
List.from = function(obj) {
const list = new List()
for (const value of obj) {
list.pushBack(value)
}
return list
}
mixinClasses(List, SequenceContainer)
export class ListItem {
constructor(value) {
this.value = value
this._next = undefined
this._prev = undefined
}
get next() { return this._next }
get prev() { return this._prev }
}
export class ListIterator {
constructor(item) {
this._item = item
}
clone() {
return new ListIterator(this._item)
}
copy(rhs) {
this._item = rhs._item
return this
}
deref() {
return this._item
}
eq(rhs) {
return this._item == rhs._item
}
inc() {
this._item = this._item.next
return this
}
dec() {
this._item = this._item.prev
return this
}
}
mixinClasses(ListIterator, BidirectionalIterator)