1 /* 2 * Copyright (c) 2012-2018 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 module antlr.v4.runtime.misc.IntegerList; 8 9 import antlr.v4.runtime.IllegalArgumentException; 10 import std.conv; 11 import std.format; 12 import std.range; 13 import std.typecons; 14 15 /** 16 * A buffert list of interger values 17 */ 18 class IntegerList 19 { 20 21 /** 22 * @uml 23 * @read 24 */ 25 public int[] data_; 26 27 public this() 28 { 29 } 30 31 public this(int capacity) 32 { 33 if (capacity < 0) { 34 throw new IllegalArgumentException("Capacity can't be a negativ value!"); 35 } 36 if (capacity) 37 { 38 data_.reserve(capacity); 39 } 40 } 41 42 public this(IntegerList list) 43 { 44 data_ = list.data; 45 //size_ = list.size; 46 } 47 48 public this(int[] list) 49 { 50 foreach (value; list) { 51 add(value); 52 } 53 } 54 55 /** 56 * @uml 57 * @final 58 */ 59 public final void add(int value) 60 { 61 data_ ~= value; 62 } 63 64 /** 65 * @uml 66 * @final 67 */ 68 public final void addAll(int[] array) 69 { 70 foreach (value; array) { 71 add(value); 72 } 73 } 74 75 public void addAll(IntegerList list) 76 { 77 foreach (value; list.data) { 78 add(value); 79 } 80 } 81 82 /** 83 * @uml 84 * @final 85 */ 86 public final int get(int index) 87 in 88 { 89 assert(index >= 0 || index < data_.length); 90 } 91 do 92 { 93 return data_[index]; 94 } 95 96 /** 97 * @uml 98 * @final 99 */ 100 public final bool contains(int value) 101 { 102 import std.algorithm.searching : canFind; 103 return data_.canFind(value); 104 } 105 106 /** 107 * @uml 108 * @final 109 */ 110 public final int set(int index, int value) 111 in 112 { 113 assert(index >= 0 || index < data_.length); 114 } 115 do 116 { 117 int previous = data_[index]; 118 data_[index] = value; 119 return previous; 120 } 121 122 /** 123 * @uml 124 * @final 125 */ 126 public final int removeAt(int index) 127 { 128 int value = get(index); 129 import std.algorithm.mutation : remove; 130 data_ = remove(data_, index); 131 return value; 132 } 133 134 /** 135 * @uml 136 * @final 137 */ 138 public final void removeRange(int fromIndex, int toIndex) 139 in 140 { 141 assert(fromIndex >= 0 || toIndex >= 0 || fromIndex <= data_.length || toIndex <= data_.length, "IndexOutOfBoundsException"); 142 assert(fromIndex <= toIndex, "IllegalArgumentException"); 143 } 144 do 145 { 146 import std.algorithm.mutation : remove; 147 data_ = remove(data_, tuple(fromIndex, toIndex+1)); 148 } 149 150 /** 151 * @uml 152 * @final 153 */ 154 public final bool isEmpty() 155 { 156 return data_.length == 0; 157 } 158 159 /** 160 * @uml 161 * @final 162 */ 163 public final int size() 164 { 165 return to!int(data_.length); 166 } 167 168 /** 169 * @uml 170 * @final 171 * @property 172 */ 173 public final @property void clear() 174 { 175 data_.length = 0; 176 } 177 178 /** 179 * @uml 180 * @final 181 * @property 182 */ 183 public final @property int[] toArray() 184 { 185 return data_; 186 } 187 188 public void sort() 189 { 190 import std.algorithm.sorting: sort; 191 data_.sort; 192 } 193 194 /** 195 * Compares the specified object with this list for equality. Returns 196 * {@code true} if and only if the specified object is also an {@link IntegerList}, 197 * both lists have the same size, and all corresponding pairs of elements in 198 * the two lists are equal. In other words, two lists are defined to be 199 * equal if they contain the same elements in the same order. 200 * <p> 201 * This implementation first checks if the specified object is this 202 * list. If so, it returns {@code true}; if not, it checks if the 203 * specified object is an {@link IntegerList}. If not, it returns {@code false}; 204 * if so, it checks the size of both lists. If the lists are not the same size, 205 * it returns {@code false}; otherwise it iterates over both lists, comparing 206 * corresponding pairs of elements. If any comparison returns {@code false}, 207 * this method returns {@code false}. 208 * 209 * @param o the object to be compared for equality with this list 210 * @return {@code true} if the specified object is equal to this list 211 * @uml 212 * @override 213 */ 214 public override bool opEquals(Object o) 215 { 216 if (o is this) { 217 return true; 218 } 219 220 if (!cast(IntegerList)o) { 221 return false; 222 } 223 224 IntegerList other = cast(IntegerList)o; 225 if (data_.length != other.size) { 226 return false; 227 } 228 import std.algorithm.comparison : equal; 229 return data_.equal(other.data); 230 } 231 232 /** 233 * Returns the hash code value for this list. 234 * 235 * <p>This implementation uses exactly the code that is used to define the 236 * list hash function in the documentation for the {@link List#hashCode} 237 * method.</p> 238 * 239 * @return the hash code value for this list 240 * @uml 241 * @override 242 * @safe 243 * @nothrow 244 */ 245 public override size_t toHash() @safe nothrow 246 { 247 int hashCode = 1; 248 for (int i = 0; i < data_.length; i++) { 249 hashCode = 31*hashCode + data_[i]; 250 } 251 return hashCode; 252 } 253 254 /** 255 * Returns a string representation of this list. 256 * @uml 257 * @override 258 */ 259 public override string toString() 260 { 261 return format("%s", data_); 262 } 263 264 public final int[] data() 265 { 266 return this.data_.dup; 267 } 268 269 } 270 271 version(unittest) { 272 import dshould : be, equal, not, should; 273 import dshould.thrown; 274 import unit_threaded; 275 276 class Test { 277 278 @Tags("IntegerList") 279 @("TestEmpty") 280 unittest { 281 auto il = new IntegerList; 282 il.should.not.be(null); 283 il.isEmpty.should.equal(true); 284 il.toArray.should.equal([]); 285 } 286 287 @Tags("IntegerList") 288 @("Capacity") 289 unittest { 290 auto il = new IntegerList(20); 291 il.should.not.be(null); 292 il.addAll([3, 17, 55, 12, 1, 7]); 293 il.toArray.should.equal([3, 17, 55, 12, 1, 7]); 294 il.toString.should.equal("[3, 17, 55, 12, 1, 7]"); 295 (new IntegerList(-3)) 296 .should 297 .throwAn!IllegalArgumentException 298 .where.msg.should.equal("Capacity can't be a negativ value!"); 299 } 300 301 @Tags("IntegerList") 302 @("SetGet") 303 unittest { 304 auto il = new IntegerList([7, 2, 5, 15, 40]); 305 il.contains(3).should.equal(false); 306 il.contains(5).should.equal(true); 307 il.get(2).should.equal(5); 308 il.sort; 309 il.toString.should.equal("[2, 5, 7, 15, 40]"); 310 il.set(3, 2); 311 il.toString.should.equal("[2, 5, 7, 2, 40]"); 312 } 313 314 @Tags("IntegerList") 315 @("Hash") 316 unittest { 317 auto il = new IntegerList([7, 5, 15, 40]); 318 auto il1 = new IntegerList; 319 il1.addAll(il); 320 il.toHash.should.equal(1137368); 321 il1.toHash.should.equal(1137368); 322 } 323 324 @Tags("IntegerList") 325 @("Remove") 326 unittest { 327 auto il = new IntegerList([7, 5, 15, 40]); 328 il.toString.should.equal("[7, 5, 15, 40]"); 329 il.removeAt(2); 330 il.toString.should.equal("[7, 5, 40]"); 331 il.removeAt(2); 332 il.toString.should.equal("[7, 5]"); 333 il.removeRange(0, 1); 334 il.isEmpty.should.equal(true); 335 il.addAll([4, 2, 1, 33, 22, 11, 13]); 336 il.removeRange(2, 4); 337 il.toString.should.equal("[4, 2, 11, 13]"); 338 } 339 340 @Tags("IntegerList") 341 @("Compare") 342 unittest { 343 auto il = new IntegerList([7, 2, 5, 15, 40]); 344 il.contains(3).should.equal(false); 345 il.contains(5).should.equal(true); 346 il.opEquals(il).should.equal(true); 347 il.get(2).should.equal(5); 348 auto il1 = new IntegerList(il); 349 il1.should.not.be(null); 350 il.toString.should.equal("[7, 2, 5, 15, 40]"); 351 il1.toString.should.equal("[7, 2, 5, 15, 40]"); 352 il.should.equal(il1); 353 il.sort; 354 il.toString.should.equal("[2, 5, 7, 15, 40]"); 355 il.should.not.equal(il1); 356 il.clear; 357 il.toString.should.equal("[]"); 358 il.should.not.equal(il1); 359 class A { 360 } 361 auto a = new A; 362 il.should.not.equal(a); 363 } 364 } 365 }