All Downloads are FREE. Search and download functionalities are using the official Maven repository.

parsley.internal.collection.mutable.DoublyLinkedList.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 Parsley Contributors 
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package parsley.internal.collection.mutable

import scala.collection.AbstractIterator

import parsley.XAssert._

import DoublyLinkedList.Node

private [internal] class DoublyLinkedList[A] private
    (private var start: Node[A],
     private var end: Node[A]) extends Iterable[A] {

    private def this() = this(null, null)

    private def unsafeAddOne(x: A): this.type = {
        assume(this.nonEmpty, "list is empty when unsafely adding an element")
        val next = new Node(x, null, this.end)
        this.end.next = next
        this.end = next
        this
    }
    def addOne(x: A): this.type = {
        if (this.start == null) {
            this.start = new Node(x, null, null)
            this.end = this.start
            this
        }
        else unsafeAddOne(x)
    }
    def +=(x: A): this.type = addOne(x)

    def addAll(xs: Iterable[A]): this.type = addAll(xs.iterator)
    def addAll(it: Iterator[A]): this.type = {
        if (it.hasNext) {
            addOne(it.next())
            for (x <- it) {
                unsafeAddOne(x)
            }
        }
        this
    }

    def prependOne(x: A): this.type = {
        val start = new Node(x, this.start, null)
        this.start = start
        if (this.end == null) this.end = this.start
        this
    }

    def stealAll(other: DoublyLinkedList[A]): this.type = if (other.nonEmpty) {
        if (this.end != null) {
            this.end.next = other.start
            other.start.prev = this.end
        }
        else this.start = other.start
        this.end = other.end
        other.start = null
        other.end = null
        this
    } else this

    override def isEmpty: Boolean = start == null

    override def lastOption: Option[A] = if (end != null) Some(end.x) else None
    override def headOption: Option[A] = if (start != null) Some(start.x) else None
    override def last: A = if (end != null) end.x else throw new NoSuchElementException("last on the empty list") // scalastyle:ignore throw
    override def head: A = if (start != null) start.x else throw new NoSuchElementException("head on the empty list") // scalastyle:ignore throw

    def clear(): Unit = {
        start = null
        end = null
    }

    def initInPlace(): this.type = {
        if (this.end == null) throw new IllegalStateException("Cannot take init of the empty list") // scalastyle:ignore throw
        this.end = this.end.prev
        if (this.end != null) this.end.next = null
        else this.start = null
        this
    }

    override def iterator: Iterator[A] = new AbstractIterator[A] {
        var current: Node[A] = start
        def hasNext = current != null
        def next() = { val r = current.x; current = current.next; r }
    }

    def reverseIterator: Iterator[A] = new AbstractIterator[A] {
        var current: Node[A] = end
        def hasNext = current != null
        def next() = { val r = current.x; current = current.prev; r }
    }
}

private [internal] object DoublyLinkedList {
    private class Node[A](val x: A, var next: Node[A], var prev: Node[A])
    def empty[A]: DoublyLinkedList[A] = new DoublyLinkedList[A]
    def apply[A](x: A, xs: A*): DoublyLinkedList[A] = {
        val list = new DoublyLinkedList[A]
        list += x
        for (x <- xs) list.unsafeAddOne(x)
        list
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy