1 /* 2 * Copyright the original author or authors. 3 * 4 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.mozilla.org/MPL/MPL-1.1.html 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import org.as2lib.env.except.IllegalArgumentException; 18 import org.as2lib.data.holder.IndexOutOfBoundsException; 19 import org.as2lib.data.holder.Iterator; 20 import org.as2lib.data.holder.List; 21 import org.as2lib.data.holder.list.AbstractList; 22 import org.as2lib.data.holder.list.ListIterator; 23 24 /** 25 * {@code SubList} represents a part of a wrapped list. This part is specified by a 26 * range from one index to another index. Every changes that are made to this list are 27 * actually made to the wrapped list. You can nevertheless treat this list 28 * implementation as any other; there is no difference in usage. 29 * 30 * @author Simon Wacker 31 */ 32 class org.as2lib.data.holder.list.SubList extends AbstractList implements List { 33 34 /** Makes the static variables of the super-class accessible through this class. */ 35 private static var __proto__:Function = AbstractList; 36 37 /** The list this is a sub-list of. */ 38 private var list:List; 39 40 /** The start index in the main-list. */ 41 private var offset:Number; 42 43 /** The size of this sub-list. */ 44 private var length:Number; 45 46 /** 47 * Constructs a new {@code SubList} instance. 48 * 49 * @param list the list this is a sub-list of 50 * @param fromIndex the start index of this sub-list (inclusive) 51 * @param toIndex the end index of this sub-list (exclusive) 52 * @throws IllegalArgumentException if argument {@code list} is {@code null} or 53 * {@code undefined} 54 * @throws IndexOutOfBoundsException if argument {@code fromIndex} is less than 0 55 * @throws IndexOutOfBoundsException if argument {@code toIndex} is greater than 56 * the size of the passed-in {@code list} 57 * @throws IndexOutOfBoundsException if argument {@code fromIndex} is greater than 58 * {@code toIndex} 59 */ 60 public function SubList(list:List, fromIndex:Number, toIndex:Number) { 61 if (!list) throw new IllegalArgumentException("Argument 'list' [" + list + "] must not be 'null' nor 'undefined'.", this, arguments); 62 if (fromIndex < 0) throw new IndexOutOfBoundsException("Argument 'fromIndex' [" + fromIndex + "] must not be less than 0.", this, arguments); 63 if (toIndex > list.size()) throw new IndexOutOfBoundsException("Argument 'toIndex' [" + toIndex + "] must not be greater than the size of the passed-in 'list' [" + list.size() + "].", this, arguments); 64 if (fromIndex > toIndex) throw new IndexOutOfBoundsException("Argument 'fromIndex' [" + fromIndex + "] must not be greater than argument 'toIndex' [" + toIndex + "].", this, arguments); 65 this.list = list; 66 this.offset = fromIndex; 67 this.length = toIndex - fromIndex; 68 } 69 70 /** 71 * Sets {@code value} to given {@code index} on this list. 72 * 73 * @param index the index of {@code value} 74 * @param value the {@code value} to set to given {@code index} 75 * @return the value that was orignially at given {@code index} 76 * @throws IndexOutOfBoundsException if given {@code index} is less than 0 or 77 * equal to or greater than this list's size 78 */ 79 public function set(index:Number, value) { 80 if (index < 0 || index >= size()) { 81 throw new IndexOutOfBoundsException("Argument 'index' [" + index + "] is out of range, this is less than 0 or equal to or greater than this list's size [" + size() + "].", this, arguments); 82 } 83 return this.list.set(offset + index, value); 84 } 85 86 /** 87 * Returns the value at given {@code index}. 88 * 89 * @param index the index to return the value of 90 * @return the value that is at given {@code index} 91 * @throws IndexOutOfBoundsException if given {@code index} is less than 0 or 92 * equal to or greater than this list's size 93 */ 94 public function get(index:Number) { 95 if (index < 0 || index >= size()) { 96 throw new IndexOutOfBoundsException("Argument 'index' [" + index + "] is out of range, this is less than 0 or equal to or greater than this list's size [" + size() + "].", this, arguments); 97 } 98 return this.list.get(offset + index); 99 } 100 101 /** 102 * Inserts {@code value} at the given {@code index}. 103 * 104 * <p>The element that is currently at the given {@code index} is shifted by one to 105 * the right, as well as any subsequent elements. 106 * 107 * @param index the index at which to insert the {@code value} 108 * @param value the value to insert 109 * @throws IndexOutOfBoundsException if the given {@code index} is not in range, 110 * this is less than 0 or greater than this list's size 111 */ 112 public function insertByIndexAndValue(index:Number, value):Void { 113 if (index < 0 || index > size()) { 114 throw new IndexOutOfBoundsException("Argument 'index' [" + index + "] is out of range, this is less than 0 or greater than this list's size [" + size() + "].", this, arguments); 115 } 116 this.list.insertByIndexAndValue(offset + index, value); 117 this.length++; 118 } 119 120 /** 121 * Removes the value at given {@code index} from this list and returns it. 122 * 123 * @param index the index of the value to remove 124 * @return the removed value that was originally at given {@code index} 125 * @throws IndexOutOfBoundsException if given {@code index} is less than 0 or 126 * equal to or greater than this list's size 127 */ 128 public function removeByIndex(index:Number) { 129 if (index < 0 || index >= size()) { 130 throw new IndexOutOfBoundsException("Argument 'index' [" + index + "] is out of range, this is less than 0 or equal to or greater than this list's size [" + size() + "].", this, arguments); 131 } 132 // list.removeByIndex may throw an exception, in this case the size must not be reduced 133 var result = this.list.removeByIndex(offset + index); 134 this.length--; 135 return result; 136 } 137 138 /** 139 * Removes all values from this list. 140 */ 141 public function clear(Void):Void { 142 do { 143 this.list.removeByIndex(this.offset); 144 } while (--this.length > 0); 145 } 146 147 /** 148 * Returns the number of added values. 149 * 150 * @return the number of added values 151 */ 152 public function size(Void):Number { 153 return this.length; 154 } 155 156 /** 157 * Returns the iterator to iterate over this list. 158 * 159 * @return the iterator to iterate over this list 160 */ 161 public function iterator(Void):Iterator { 162 return new ListIterator(this); 163 } 164 165 /** 166 * Returns the array representation of this list. 167 * 168 * @return the array representation of this list 169 */ 170 public function toArray(Void):Array { 171 return this.list.toArray().slice(this.offset, this.offset + this.length); 172 } 173 174 }