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