Phaser Source: src/utils/LinkedList.js

# Source: src/utils/LinkedList.js

    /**
    * @author       Richard Davey <rich@photonstorm.com>
    * @copyright    2016 Photon Storm Ltd.
    * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
    */

    /**
    * A basic Linked List data structure.
    *
    * This implementation _modifies_ the `prev` and `next` properties of each item added:
    * - The `prev` and `next` properties must be writable and should not be used for any other purpose.
    * - Items _cannot_ be added to multiple LinkedLists at the same time.
    * - Only objects can be added.
    *
    * @class Phaser.LinkedList
    * @constructor
    */
    Phaser.LinkedList = function () {

        /**
        * Next element in the list.
        * @property {object} next
        * @default
        */
        this.next = null;

        /**
        * Previous element in the list.
        * @property {object} prev
        * @default
        */
        this.prev = null;

        /**
        * First element in the list.
        * @property {object} first
        * @default
        */
        this.first = null;

        /**
        * Last element in the list.
        * @property {object} last
        * @default
        */
        this.last = null;

        /**
        * Number of elements in the list.
        * @property {integer} total
        * @default
        */
        this.total = 0;

    };

    Phaser.LinkedList.prototype = {

        /**
        * Adds a new element to this linked list.
        *
        * @method Phaser.LinkedList#add
        * @param {object} item - The element to add to this list. Can be a Phaser.Sprite or any other object you need to quickly iterate through.
        * @return {object} The item that was added.
        */
        add: function (item) {

            //  If the list is empty
            if (this.total === 0 && this.first === null && this.last === null)
            {
                this.first = item;
                this.last = item;
                this.next = item;
                item.prev = this;
                this.total++;
                return item;
            }

            //  Gets appended to the end of the list, regardless of anything, and it won't have any children of its own (non-nested list)
            this.last.next = item;

            item.prev = this.last;

            this.last = item;

            this.total++;

            return item;

        },

        /**
        * Resets the first, last, next and previous node pointers in this list.
        *
        * @method Phaser.LinkedList#reset
        */
        reset: function () {

            this.first = null;
            this.last = null;
            this.next = null;
            this.prev = null;
            this.total = 0;

        },

        /**
        * Removes the given element from this linked list if it exists.
        *
        * @method Phaser.LinkedList#remove
        * @param {object} item - The item to be removed from the list.
        */
        remove: function (item) {

            if (this.total === 1)
            {
                this.reset();
                item.next = item.prev = null;
                return;
            }

            if (item === this.first)
            {
                // It was 'first', make 'first' point to first.next
                this.first = this.first.next;
            }
            else if (item === this.last)
            {
                // It was 'last', make 'last' point to last.prev
                this.last = this.last.prev;
            }

            if (item.prev)
            {
                // make item.prev.next point to childs.next instead of item
                item.prev.next = item.next;
            }

            if (item.next)
            {
                // make item.next.prev point to item.prev instead of item
                item.next.prev = item.prev;
            }

            item.next = item.prev = null;

            if (this.first === null )
            {
                this.last = null;
            }

            this.total--;

        },

        /**
        * Calls a function on all members of this list, using the member as the context for the callback.
        * The function must exist on the member.
        *
        * @method Phaser.LinkedList#callAll
        * @param {function} callback - The function to call.
        */
        callAll: function (callback) {

            if (!this.first || !this.last)
            {
                return;
            }

            var entity = this.first;

            do
            {
                if (entity && entity[callback])
                {
                    entity[callback].call(entity);
                }

                entity = entity.next;

            }
            while (entity !== this.last.next);

        }

    };

    Phaser.LinkedList.prototype.constructor = Phaser.LinkedList;