tikhomirov@674: /* tikhomirov@674: * Copyright (c) 2013 TMate Software Ltd tikhomirov@674: * tikhomirov@674: * This program is free software; you can redistribute it and/or modify tikhomirov@674: * it under the terms of the GNU General Public License as published by tikhomirov@674: * the Free Software Foundation; version 2 of the License. tikhomirov@674: * tikhomirov@674: * This program is distributed in the hope that it will be useful, tikhomirov@674: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@674: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@674: * GNU General Public License for more details. tikhomirov@674: * tikhomirov@674: * For information on how to redistribute this software under tikhomirov@674: * the terms of a license other than GNU General Public License tikhomirov@674: * contact TMate Software at support@hg4j.com tikhomirov@674: */ tikhomirov@674: package org.tmatesoft.hg.internal; tikhomirov@674: tikhomirov@674: import java.util.Iterator; tikhomirov@674: import java.util.NoSuchElementException; tikhomirov@674: tikhomirov@674: /** tikhomirov@674: * tikhomirov@674: * @author Artem Tikhomirov tikhomirov@674: * @author TMate Software Ltd. tikhomirov@674: */ tikhomirov@680: public final class IntSliceSeq implements Iterable, Cloneable { tikhomirov@674: private final IntVector slices; tikhomirov@674: private final int slice; tikhomirov@674: tikhomirov@674: public IntSliceSeq(int sliceSize) { tikhomirov@674: // initial size/grow values are pure guess tikhomirov@674: this(sliceSize, 10, 5); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntSliceSeq(int sliceSize, int initialSlices, int slicesToGrow) { tikhomirov@674: slices = new IntVector(sliceSize * initialSlices, sliceSize*slicesToGrow); tikhomirov@674: slice = sliceSize; tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntSliceSeq add(int... values) { tikhomirov@680: checkValuesAny(values); tikhomirov@674: slices.add(values); tikhomirov@674: return this; tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntSliceSeq set(int sliceIndex, int... values) { tikhomirov@680: checkValuesExact(values); tikhomirov@674: for (int i = 0, j = sliceIndex*slice; i < slice; i++,j++) { tikhomirov@674: slices.set(j, values[i]); tikhomirov@674: } tikhomirov@674: return this; tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntTuple get(int sliceIndex) { tikhomirov@674: checkArgRange(size(), sliceIndex); tikhomirov@674: return new IntTuple(slice).set(slices, sliceIndex*slice); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public int get(int sliceIndex, int valueIndex) { tikhomirov@674: checkArgRange(size(), sliceIndex); tikhomirov@674: checkArgRange(slice, valueIndex); tikhomirov@674: return slices.get(sliceIndex*slice + valueIndex); tikhomirov@674: } tikhomirov@674: tikhomirov@680: public void addAll(IntSliceSeq other) { tikhomirov@680: if (other.slice != this.slice) { tikhomirov@680: throw new IllegalArgumentException(String.format("Tuple size doesn't match: %d and %d", slice, other.slice)); tikhomirov@680: } tikhomirov@680: slices.addAll(other.slices); tikhomirov@680: } tikhomirov@680: tikhomirov@674: public int size() { tikhomirov@674: return slices.size() / slice; tikhomirov@674: } tikhomirov@674: tikhomirov@674: public int sliceSize() { tikhomirov@674: return slice; tikhomirov@674: } tikhomirov@674: tikhomirov@674: public void clear() { tikhomirov@674: slices.clear(); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntTuple last() { tikhomirov@674: int lastElementIndex = (size() - 1); tikhomirov@674: if (lastElementIndex < 0) { tikhomirov@674: throw new NoSuchElementException(); tikhomirov@674: } tikhomirov@674: return get(lastElementIndex); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public Iterator iterator() { tikhomirov@674: return new Iterator() { tikhomirov@674: private final IntTuple t = new IntTuple(slice); tikhomirov@674: private int next = 0; tikhomirov@674: tikhomirov@674: public boolean hasNext() { tikhomirov@674: return next < size(); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public IntTuple next() { tikhomirov@674: return t.set(slices, next++*slice); tikhomirov@674: } tikhomirov@674: tikhomirov@674: public void remove() { tikhomirov@674: throw new UnsupportedOperationException(); tikhomirov@674: } tikhomirov@674: }; tikhomirov@674: } tikhomirov@679: tikhomirov@679: @Override tikhomirov@679: public String toString() { tikhomirov@679: StringBuilder sb = new StringBuilder(); tikhomirov@679: for (int i = 0; i < size(); i++) { tikhomirov@679: sb.append('('); tikhomirov@679: for (int j = 0; j < slice; j++) { tikhomirov@679: sb.append(slices.get(i*slice + j)); tikhomirov@679: sb.append(','); tikhomirov@679: } tikhomirov@679: sb.setLength(sb.length() - 1); tikhomirov@679: sb.append(')'); tikhomirov@679: sb.append(' '); tikhomirov@679: } tikhomirov@679: return sb.toString(); tikhomirov@679: } tikhomirov@680: tikhomirov@680: @Override tikhomirov@680: public IntSliceSeq clone() { tikhomirov@680: try { tikhomirov@680: return (IntSliceSeq) super.clone(); tikhomirov@680: } catch (CloneNotSupportedException ex) { tikhomirov@680: throw new Error(ex); tikhomirov@680: } tikhomirov@680: } tikhomirov@674: tikhomirov@674: private void checkArgRange(int rangeSize, int index) { tikhomirov@674: if (index >= 0 && index < rangeSize) { tikhomirov@674: return; tikhomirov@674: } tikhomirov@674: throw new IllegalArgumentException(String.valueOf(index)); tikhomirov@674: } tikhomirov@680: private void checkValuesExact(int[] values) { tikhomirov@674: if (values == null || values.length != slice) { tikhomirov@674: throw new IllegalArgumentException(String.valueOf(values == null ? values : values.length)); tikhomirov@674: } tikhomirov@674: } tikhomirov@680: private void checkValuesAny(int[] values) { tikhomirov@680: if (values == null || values.length % slice != 0) { tikhomirov@680: throw new IllegalArgumentException(String.valueOf(values == null ? values : values.length)); tikhomirov@680: } tikhomirov@680: } tikhomirov@674: }