package at.yawk.numaec;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ConcurrentModificationException;
import org.eclipse.collections.api.LazyCharIterable;
import org.eclipse.collections.api.CharIterable;
import org.eclipse.collections.api.block.function.primitive.ObjectCharIntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.ObjectCharToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.CharToObjectFunction;
import org.eclipse.collections.api.block.predicate.primitive.CharPredicate;
import org.eclipse.collections.api.block.procedure.primitive.CharIntProcedure;
import org.eclipse.collections.api.block.procedure.primitive.CharProcedure;
import org.eclipse.collections.api.iterator.MutableCharIterator;
import org.eclipse.collections.api.iterator.CharIterator;
import org.eclipse.collections.api.list.ListIterable;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.list.primitive.ImmutableCharList;
import org.eclipse.collections.api.list.primitive.MutableCharList;
import org.eclipse.collections.api.list.primitive.CharList;
import org.eclipse.collections.impl.lazy.primitive.ReverseCharIterable;
import org.eclipse.collections.impl.list.mutable.primitive.SynchronizedCharList;
import org.eclipse.collections.impl.list.mutable.primitive.UnmodifiableCharList;
import org.eclipse.collections.impl.primitive.AbstractCharIterable;
class CharBufferListImpl extends AbstractCharIterable implements CharBufferList {
private static final int INITIAL_CAPACITY = 16;
final LargeByteBufferAllocator allocator;
LargeByteBuffer buffer;
int size;
CharBufferListImpl(LargeByteBufferAllocator allocator) {
this.allocator = allocator;
buffer = LargeByteBuffer.EMPTY;
}
CharBufferListImpl(LargeByteBufferAllocator allocator, int initialCapacity) {
this.allocator = allocator;
buffer = allocator.allocate(scale(initialCapacity));
}
@Override
public void close() {
buffer.close();
buffer = null;
}
protected long scale(int index) {
return ((long) index) * Character.BYTES;
}
@Override
public CharIterator charIterator() {
return new Itr();
}
@Override
public char[] toArray() {
char[] array = new char[size];
for (int i = 0; i < size; i++) {
array[i] = get(i);
}
return array;
}
@Override
public boolean contains(char value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return true;
}
}
return false;
}
@Override
public void forEach(CharProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i));
}
}
@Override
public void each(CharProcedure procedure) {
forEach(procedure);
}
@Override
public char get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
return buffer.getChar(scale(index));
}
}
@Override
public long
dotProduct(CharList list) {
long
sum = 0;
int i = 0;
CharIterator itr = list.charIterator();
while (i < size && itr.hasNext()) {
sum += get(i++) * itr.next();
}
if (itr.hasNext() || i < size) {
throw new IllegalArgumentException("Size mismatch");
}
return sum;
}
@Override
public int binarySearch(char value) {
int low = 0;
int high = size - 1;
while (low <= high) {
int mid = (low + high) / 2;
char pivot = get(mid);
if (pivot < value) {
low = mid + 1;
} else if (pivot > value) {
high = mid - 1;
} else {
return mid;
}
}
return ~low;
}
@Override
public int indexOf(char value) {
for (int i = 0; i < size; i++) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(char value) {
for (int i = size - 1; i >= 0; i--) {
if (get(i) == value) {
return i;
}
}
return -1;
}
@Override
public char getLast() {
return get(size - 1);
}
@Override
public LazyCharIterable asReversed() {
return ReverseCharIterable.adapt(this);
}
@Override
public char getFirst() {
return get(0);
}
@Override
public CharList select(CharPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public CharList reject(CharPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> ListIterable<V> collect(CharToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public char detectIfNone(CharPredicate predicate, char ifNone) {
for (int i = 0; i < size; i++) {
char element = get(i);
if (predicate.accept(element)) {
return element;
}
}
return ifNone;
}
@Override
public int count(CharPredicate predicate) {
int count = 0;
for (int i = 0; i < size; i++) {
if (predicate.accept(get(i))) {
count++;
}
}
return count;
}
@Override
public boolean anySatisfy(CharPredicate predicate) {
for (int i = 0; i < size; i++) {
char element = get(i);
if (predicate.accept(element)) {
return true;
}
}
return false;
}
@Override
public boolean allSatisfy(CharPredicate predicate) {
for (int i = 0; i < size; i++) {
char element = get(i);
if (!predicate.accept(element)) {
return false;
}
}
return true;
}
@Override
public boolean noneSatisfy(CharPredicate predicate) {
return !anySatisfy(predicate);
}
@Override
public <T> T injectInto(T injectedValue, ObjectCharToObjectFunction<? super T, ? extends T> function) {
for (int i = 0; i < size; i++) {
injectedValue = function.valueOf(injectedValue, get(i));
}
return injectedValue;
}
@Override
public <T> T injectIntoWithIndex(T injectedValue, ObjectCharIntToObjectFunction<? super T, ? extends T> function) {
for (int i = 0; i < size; i++) {
injectedValue = function.valueOf(injectedValue, get(i), i);
}
return injectedValue;
}
@Override
public long
sum() {
long
sum = 0;
for (int i = 0; i < size; i++) {
sum += get(i);
}
return sum;
}
@Override
public char max() {
char max = get(0);
for (int i = 1; i < size; i++) {
char item = get(i);
if (item > max) {
return item;
}
}
return max;
}
@Override
public char min() {
char min = get(0);
for (int i = 1; i < size; i++) {
char item = get(i);
if (item < min) {
return item;
}
}
return min;
}
@Override
public ImmutableCharList toImmutable() {
throw new UnsupportedOperationException();
}
@Override
public CharList distinct() {
throw new UnsupportedOperationException();
}
@Override
public void forEachWithIndex(CharIntProcedure procedure) {
for (int i = 0; i < size; i++) {
procedure.value(get(i), i);
}
}
@Override
public CharList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public CharList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return size;
}
@Override
public void appendString(Appendable appendable, String start, String separator, String end) {
try {
appendable.append(start);
for (int i = 0; i < size; i++) {
if (i != 0) {
appendable.append(separator);
}
appendable.append(String.valueOf(get(i)));
}
appendable.append(end);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public boolean equals(Object o) {
if (o instanceof CharList) {
CharList other = (CharList) o;
int expectedSize = other.size();
if (expectedSize == this.size()) {
CharIterator j = other.charIterator();
int i = 0;
while (i < expectedSize) {
if (!j.hasNext()) { throw new ConcurrentModificationException(); }
if (j.next() != get(i)) { return false; }
i++;
}
if (j.hasNext()) { throw new ConcurrentModificationException(); }
return true;
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
int hashCode = 1;
for (int i = 0; i < size(); i++) {
hashCode *= 31;
hashCode += get(i);
}
return hashCode;
}
class Itr implements CharIterator {
int i;
@Override
public char next() {
return get(i++);
}
@Override
public boolean hasNext() {
return i < size;
}
}
public static class Mutable extends CharBufferListImpl implements MutableCharBufferList {
Mutable(LargeByteBufferAllocator allocator) {
super(allocator);
}
Mutable(LargeByteBufferAllocator allocator, int initialCapacity) {
super(allocator, initialCapacity);
}
private void ensureCapacity(int capacity) {
long requiredCapacity = scale(capacity);
long currentCapacity = buffer.size();
if (requiredCapacity > currentCapacity) {
long newCapacity = currentCapacity == 0 ? scale(INITIAL_CAPACITY) : currentCapacity;
while (requiredCapacity > newCapacity) {
newCapacity += newCapacity >> 1;
}
LargeByteBuffer reallocated = buffer.reallocate(newCapacity);
if (reallocated != null) {
this.buffer = reallocated;
} else {
@SuppressWarnings("resource")
LargeByteBuffer swap = allocator.allocate(newCapacity);
try {
swap.copyFrom(buffer, 0, 0, scale(size));
LargeByteBuffer tmp = swap;
swap = this.buffer;
this.buffer = tmp;
} finally {
swap.close();
}
}
}
}
@Override
public void addAtIndex(int index, char element) {
if (index == size) {
add(element);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else {
ensureCapacity(size + 1);
buffer.copyFrom(buffer, scale(index), scale(index + 1), scale(size - index));
buffer.setChar(scale(index), element);
size++;
}
}
@Override
public boolean addAllAtIndex(int index, char... source) {
if (index == size) {
return addAll(source);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else if (source.length == 0) {
return false;
} else {
ensureCapacity(size + source.length);
buffer.copyFrom(buffer, scale(index), scale(index + source.length), scale(size - index));
for (int i = 0; i < source.length; i++) {
buffer.setChar(scale(index + i), source[i]);
}
size += source.length;
return true;
}
}
@Override
public boolean addAllAtIndex(int index, CharIterable source) {
if (index == size) {
return addAll(source);
} else if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
} else if (source.isEmpty()) {
return false;
} else {
int expectedSize = source.size();
ensureCapacity(size + expectedSize);
buffer.copyFrom(buffer, scale(index), scale(index + expectedSize), scale(size - index));
CharIterator itr = source.charIterator();
for (int i = 0; i < expectedSize; i++) {
if (!itr.hasNext()) { throw new ConcurrentModificationException(); }
buffer.setChar(scale(index + i), itr.next());
}
if (itr.hasNext()) { throw new ConcurrentModificationException(); }
size += expectedSize;
return true;
}
}
@Override
public char removeAtIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
char value = buffer.getChar(scale(index));
if (size > 1) {
buffer.copyFrom(buffer, scale(index + 1), scale(index), scale(size - index - 1));
}
size--;
return value;
}
}
@Override
public char set(int index, char element) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
} else {
char old = buffer.getChar(scale(index));
buffer.setChar(scale(index), element);
return old;
}
}
@Override
public boolean add(char element) {
ensureCapacity(size + 1);
buffer.setChar(scale(size), element);
size++;
return true;
}
@Override
public boolean addAll(char... source) {
ensureCapacity(size + source.length);
for (int i = 0; i < source.length; i++) {
buffer.setChar(scale(i + size), source[i]);
}
size += source.length;
return source.length > 0;
}
@Override
public boolean addAll(CharIterable source) {
int expectedSize = source.size();
ensureCapacity(size + expectedSize);
CharIterator itr = source.charIterator();
int i = 0;
while (itr.hasNext()) {
if (i > expectedSize) {
throw new ConcurrentModificationException();
}
buffer.setChar(scale(i + size), itr.next());
i++;
}
size += i;
return i > 0;
}
@Override
public boolean remove(char value) {
int ix = indexOf(value);
if (ix == -1) {
return false;
} else {
removeAtIndex(ix);
return true;
}
}
@Override
public boolean removeAll(CharIterable source) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(char... source) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(CharIterable elements) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(char... source) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
size = 0;
}
@Override
public MutableCharList with(char element) {
add(element);
return this;
}
@Override
public MutableCharList without(char element) {
remove(element);
return this;
}
@Override
public MutableCharList withAll(CharIterable elements) {
addAll(elements);
return this;
}
@Override
public MutableCharList withoutAll(CharIterable elements) {
removeAll(elements);
return this;
}
@Override
public MutableCharList reverseThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList sortThis() {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList asUnmodifiable() {
return new UnmodifiableCharList(this);
}
@Override
public MutableCharList asSynchronized() {
return new SynchronizedCharList(this);
}
@Override
public MutableCharIterator charIterator() {
return new Itr();
}
@Override
public MutableCharList select(CharPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList reject(CharPredicate predicate) {
throw new UnsupportedOperationException();
}
@Override
public <V> MutableList<V> collect(CharToObjectFunction<? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList toReversed() {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList distinct() {
throw new UnsupportedOperationException();
}
@Override
public MutableCharList subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
class Itr extends CharBufferListImpl.Itr implements MutableCharIterator {
int removalIndex = -1;
@Override
public char next() {
removalIndex = i;
return super.next();
}
@Override
public void remove() {
if (removalIndex == -1) { throw new IllegalStateException(); }
removeAtIndex(removalIndex);
i--;
removalIndex = -1;
}
}
}
}