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