packer.PackerDeque.scala Maven / Gradle / Ivy
// Copyright 2015-2022 by Carnegie Mellon University
// See license information in LICENSE.txt
package org.cert.netsa.mothra.packer
/**
* The type of objects that are contained in a [[PackerDeque]]. The
* contstructor is protected indicating the class is to be subclassed.
*/
private[mothra] class PackerDequeNode[T <: PackerDequeNode[T]] protected () {
var prev: T = _
var next: T = _
}
private[mothra] case class PackerDeque[T <: PackerDequeNode[T]]() {
/** The head of the deque; its `prev` is the tail of the deque. */
private[this] var root = Option.empty[T]
/** Iterates over the objects in the deque */
private[this] class Iterator(start: Option[T]) extends
scala.collection.Iterator[T]
{
private[this] var nextNode = start
def hasNext: Boolean = ( nextNode.nonEmpty )
def next(): T = {
val ret = nextNode.get
nextNode = Option(ret.next)
if ( nextNode == start ) {
nextNode = Option.empty[T]
}
ret
}
}
/** Returns an interator over the objects in the deque. */
def iterator: scala.collection.Iterator[T] = {
new Iterator(root)
}
/** Adds `newNode` after `nodePrev`. Does not move `root`. */
private[this] def _addAfter(newNode: T, nodePrev: T):
T =
{
newNode.prev = nodePrev
newNode.next = nodePrev.next
newNode.next.prev = newNode
nodePrev.next = newNode
newNode
}
/** Adds `newNode` after `nodeNext`. Does not move `root`. */
private[this] def _addBefore(newNode: T, nodeNext: T):
T =
{
newNode.next = nodeNext
newNode.prev = nodeNext.prev
newNode.prev.next = newNode
nodeNext.prev = newNode
newNode
}
/** Sets `newRoot` as `root` when the deque is empty. */
private[this] def _makeRoot(newRoot: T): T = {
newRoot.next = newRoot
newRoot.prev = newRoot
root = Option(newRoot)
newRoot
}
/** Selects the first item; throws exception when empty. */
def head: T = {
root.getOrElse {
throw new NoSuchElementException("PackerDeque is empty")
}
}
/** Optionally selects the first item. */
def headOption: Option[T] = {
root
}
/** Removes the first item and returns it; throws exception when empty. */
def removeHead: T = {
val r = root.getOrElse {
throw new NoSuchElementException("PackerDeque is empty")
}
remove(r)
}
/** Optionally removes the first item and returns it. */
def removeHeadOption: Option[T] = {
root match {
case Some(r) => Option(remove(r))
case None => root
}
}
/** Selects the last item; throws exception when empty. */
def last: T = {
val r = root.getOrElse {
throw new NoSuchElementException("PackerDeque is empty")
}
r.prev
}
/** Optionally selects the last item. */
def lastOption: Option[T] = {
root match {
case Some(r) => Option(r.prev)
case None => root
}
}
/** Removes the last item and returns it; throws exception when empty. */
def removeLast: T = {
val r = root.getOrElse {
throw new NoSuchElementException("PackerDeque is empty")
}
remove(r.prev)
}
/** Optionally removes the last item and returns it. */
def removeLastOption: Option[T] = {
root match {
case Some(r) => Option(remove(r.prev))
case None => root
}
}
/**
* Returns the number of items in the deque. Walks the deque to count the
* items.
*/
def size: Int = {
var count = 0
for ( r <- root ) {
var n = r
do {
count += 1
n = n.next
} while ( n != r );
}
count
}
/**
* Adds `newNode` to the front of the deque and makes it the `head`.
* Returns the newly added node.
*/
def prepend(newNode: T): T = {
root match {
case Some(r) =>
root = Option(_addBefore(newNode, r))
newNode
case None => _makeRoot(newNode)
}
}
/**
* Adds `newNode` to the end of the deque and makes it the `tail`. Returns
* the newly added node.
*/
def append(newNode: T): T = {
root match {
case Some(r) => _addBefore(newNode, r)
case None => _makeRoot(newNode)
}
}
/** Returns `true` when the deque is empty. */
def isEmpty: Boolean = root.isEmpty
/** Returns `true` when the deque is not empty. */
def nonEmpty: Boolean = root.nonEmpty
/** Returns `true` when `node` is in this deque. */
def contains(node: T): Boolean = {
root match {
case None => false
case Some(r) =>
var n = r
while ( n != node && n.next != r ) {
n = n.next
}
n == node
}
}
/**
* Adds `newNode` after `nodePrev`. If `nodePrev` is `tail`, `newNode`
* becomes the new tail. Returns `newNode`.
*
* Assumes `nodePrev` exists in the deque.
*/
def addAfter(newNode: T, nodePrev: T): T =
_addAfter(newNode, nodePrev)
/**
* Adds `newNode` before `nodeNext`. If `nodeNext` is `head`, `newNode`
* becomes the new head. Returns `newNode`.
*
* Assumes `nodeNext` exists in the deque.
*/
def addBefore(newNode: T, nodeNext: T): T = {
val n = _addBefore(newNode, nodeNext)
if ( root.get == nodeNext ) {
root = Option(newNode)
}
n
}
/**
* Moves `node` to the head of the deque and returns it.
*
* Assumes `node` exists in the deque.
*/
def moveToHead(node: T): T = {
for {
r <- root
// Workaround scala/bug#11175 -Ywarn-unused:params false positive
_ = r
if r != node
} {
node.prev.next = node.next
node.next.prev = node.prev
root = Option(_addBefore(node, root.get))
}
node
}
/**
* Moves `node` to the tail of the deque and returns it.
*
* Assumes `node` exists in the deque.
*/
def moveToLast(node: T): T = {
for (
r <- root
if r.prev != node
) {
if ( r == node ) {
root = Option(r.next)
}
node.prev.next = node.next
node.next.prev = node.prev
_addBefore(node, root.get)
}
node
}
/**
* Removes `node` from the deque and returns it. The `next` and `prev`
* pointers of `node` are set to itself.
*
* Assumes `node` exists in the deque.
*/
def remove(node: T): T = {
for ( r <- root ) {
if ( r == node ) {
if ( r.next == r ) {
root = Option.empty[T]
} else {
root = Option(r.next)
}
}
}
node.prev.next = node.next
node.next.prev = node.prev
node.prev = node
node.next = node
node
}
/**
* Removes all nodes from the deque. The `next` and `prev` values on each
* node are set to itself.
*/
def clear(): Unit = {
for ( r <- root ) {
var n = r.next
do {
r.next = n.next
n.next = n
n.prev = n
n = r.next
} while ( n != r );
}
root = Option.empty[T]
}
/**
* Prints the contents of the deque.
*/
def verify(): Unit = {
for ( r <- root ) {
var count = 0
var n = r
do {
println(s"${count}, value: ${n}, prev: ${n.prev}, next: ${n.next}")
n = n.next
count += 1
} while (n != r);
}
}
}
private[mothra] object PackerDeque {
/** Creates an empty deque. */
def empty[T <: PackerDequeNode[T]]: PackerDeque[T] = {
new PackerDeque[T]()
}
}
// @LICENSE_FOOTER@
//
// Copyright 2015-2022 Carnegie Mellon University. All Rights Reserved.
//
// This material is based upon work funded and supported by the
// Department of Defense and Department of Homeland Security under
// Contract No. FA8702-15-D-0002 with Carnegie Mellon University for the
// operation of the Software Engineering Institute, a federally funded
// research and development center sponsored by the United States
// Department of Defense. The U.S. Government has license rights in this
// software pursuant to DFARS 252.227.7014.
//
// NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING
// INSTITUTE MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON
// UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR
// IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF
// FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS
// OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
// MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT,
// TRADEMARK, OR COPYRIGHT INFRINGEMENT.
//
// Released under a GNU GPL 2.0-style license, please see LICENSE.txt or
// contact [email protected] for full terms.
//
// [DISTRIBUTION STATEMENT A] This material has been approved for public
// release and unlimited distribution. Please see Copyright notice for
// non-US Government use and distribution.
//
// Carnegie Mellon(R) and CERT(R) are registered in the U.S. Patent and
// Trademark Office by Carnegie Mellon University.
//
// This software includes and/or makes use of third party software each
// subject to its own license as detailed in LICENSE-thirdparty.tx
//
// DM20-1143