1 var define = require("../define").define,
  2         Collection = require("./Collection"),
  3         base = require("../base");
  4 
  5 /**
  6  * @class <p>LIFO Data structure</p>
  7  * @name Stack
  8  * @augments comb.collections.Collection
  9  * @memberOf comb.collections
 10  *
 11  * @property {Number} count the current number of elements in this queue
 12  * @property {Boolean} isEmpty true if this queue is empty
 13  * @property {Array} values a copy of the values contained in this queue
 14  */
 15 module.exports = exports = define(Collection, {
 16     instance : {
 17         /**@lends comb.collections.Stack.prototype*/
 18 
 19         constructor : function() {
 20             this.__stack = [];
 21             this.__next = -1;
 22         },
 23 
 24         /**
 25          * Add an item to the tail of this stack
 26          * @param {*} data item to qppend to this stack
 27          *
 28          */
 29         push : function(data) {
 30             this.__stack[++this.__next] = data;
 31         },
 32 
 33         /**
 34          * Removes the tail of this static
 35          * @return {*} the data at the tail of this stack
 36          */
 37         pop : function() {
 38             var ret = undefined, stack, next = this.__next;
 39             if (next >= 0) {
 40                 stack = this.__stack;
 41                 ret = stack[next];
 42                 stack[this.__next--] = undefined;
 43             }
 44             return ret;
 45         },
 46 
 47         /**
 48          * Retrieves the item at the tail of the stack without removing it
 49          *
 50          * @return {*} The element at the tail of the stack. Returns undefined if the stack is empty.
 51          */
 52         peek : function() {
 53             var ret = undefined,next = this.__next;
 54             if (next >= 0) {
 55                 ret = this.__stack[next];
 56             }
 57             return ret;
 58         },
 59 
 60          /**
 61          * Removes all items from this stack.
 62          */
 63         clear : function() {
 64             this.__stack.length = 0;
 65             this.__next = -1;
 66         },
 67 
 68         /**
 69          * Determine if this stack contains the element
 70          * @param {*} obj the object to find
 71          *
 72          * @return {Boolean} true if this stack contains the element
 73          */
 74         contains : function(obj) {
 75             return this.__stack.indexOf(obj) != -1;
 76         },
 77 
 78         /**
 79          * Removes an element from this stack.
 80          * @param {*} obj the data to remove.
 81          *
 82          * @return {Boolean} true if the element was removed, false otherwise.
 83          */
 84         remove : function(obj) {
 85             var index = this.__stack.indexOf(obj), ret = false;
 86             if (index != -1) {
 87                 if (index == this.__next) {
 88                     this.pop();
 89                 } else {
 90                     this.__stack.splice(index, 1);
 91                     this.__next--;
 92                 }
 93                 ret = true;
 94             }
 95             return ret;
 96         },
 97 
 98         getters : {
 99             count : function() {
100                 return this.__next + 1;
101             },
102 
103             isEmpty : function() {
104                 return this.__next < 0;
105             },
106 
107             values : function() {
108                 return this.__stack.slice(0, this.__next + 1).reverse();
109             }
110         }
111     }
112 });