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 (AntlrUnittest) 285 { 286 import dshould; 287 288 @("TestEmpty") 289 unittest 290 { 291 auto il = new IntegerList; 292 il.should.not.be(null); 293 il.isEmpty.should.equal(true); 294 il.toArray.should.equal([]); 295 } 296 297 @("Capacity") 298 unittest 299 { 300 auto il = new IntegerList(20); 301 il.should.not.be(null); 302 il.addAll([3, 17, 55, 12, 1, 7]); 303 il.toArray.should.equal([3, 17, 55, 12, 1, 7]); 304 il.toString.should.equal("[3, 17, 55, 12, 1, 7]"); 305 (new IntegerList(-3)).should.throwAn!IllegalArgumentException.where.msg.should.equal( 306 "Capacity can't be a negativ value!"); 307 } 308 309 @("SetGet") 310 unittest 311 { 312 auto il = new IntegerList([7, 2, 5, 15, 40]); 313 il.contains(3).should.equal(false); 314 il.contains(5).should.equal(true); 315 il.get(2).should.equal(5); 316 il.sort; 317 il.toString.should.equal("[2, 5, 7, 15, 40]"); 318 il.set(3, 2); 319 il.toString.should.equal("[2, 5, 7, 2, 40]"); 320 } 321 322 @("Hash") 323 unittest 324 { 325 auto il = new IntegerList([7, 5, 15, 40]); 326 auto il1 = new IntegerList; 327 il1.addAll(il); 328 il.toHash.should.equal(1137368); 329 il1.toHash.should.equal(1137368); 330 } 331 332 @("Remove") 333 unittest 334 { 335 auto il = new IntegerList([7, 5, 15, 40]); 336 il.toString.should.equal("[7, 5, 15, 40]"); 337 il.removeAt(2); 338 il.toString.should.equal("[7, 5, 40]"); 339 il.removeAt(2); 340 il.toString.should.equal("[7, 5]"); 341 il.removeRange(0, 1); 342 il.isEmpty.should.equal(true); 343 il.addAll([4, 2, 1, 33, 22, 11, 13]); 344 il.removeRange(2, 4); 345 il.toString.should.equal("[4, 2, 11, 13]"); 346 } 347 348 @("Compare") 349 unittest 350 { 351 auto il = new IntegerList([7, 2, 5, 15, 40]); 352 il.contains(3).should.equal(false); 353 il.contains(5).should.equal(true); 354 il.opEquals(il).should.equal(true); 355 il.get(2).should.equal(5); 356 auto il1 = new IntegerList(il); 357 il1.should.not.be(null); 358 il.toString.should.equal("[7, 2, 5, 15, 40]"); 359 il1.toString.should.equal("[7, 2, 5, 15, 40]"); 360 il.should.equal(il1); 361 il.sort; 362 il.toString.should.equal("[2, 5, 7, 15, 40]"); 363 il.should.not.equal(il1); 364 il.clear; 365 il.toString.should.equal("[]"); 366 il.should.not.equal(il1); 367 class A 368 { 369 } 370 371 auto a = new A; 372 il.should.not.equal(a); 373 } 374 }