commit 6d3f5099e660136d1a0a700ef3ff55dac72fc8c2
Author: 00asdf <53291579+00asdf@users.noreply.github.com>
Date: Tue Apr 18 04:36:04 2023 +0200
initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0683b2b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,31 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+
+.idea
\ No newline at end of file
diff --git a/GeneralUtils.iml b/GeneralUtils.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/GeneralUtils.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/dev/asdf00/general/utils/list/PrimitiveList.java b/src/dev/asdf00/general/utils/list/PrimitiveList.java
new file mode 100644
index 0000000..9be2b45
--- /dev/null
+++ b/src/dev/asdf00/general/utils/list/PrimitiveList.java
@@ -0,0 +1,162 @@
+package dev.asdf00.general.utils.list;
+
+import dev.asdf00.general.utils.list.internal.AbstractBaseList;
+import dev.asdf00.general.utils.list.internal.ByteList;
+
+public abstract class PrimitiveList extends AbstractBaseList {
+
+ public static PrimitiveList create(Class type) {
+ return create(type, 8);
+ }
+
+ public static PrimitiveList create(Class boxedType, int initial) {
+ if (Byte.class == boxedType) {
+ return (PrimitiveList) new ByteList(initial);
+ } else if (Short.class.equals(boxedType)) {
+ return null;
+ } else if (Integer.class.equals(boxedType)) {
+ return null;
+ } else if (Long.class.equals(boxedType)) {
+ return null;
+ } else if (Float.class.equals(boxedType)) {
+ return null;
+ } else if (Double.class.equals(boxedType)) {
+ return null;
+ } else if (Character.class.equals(boxedType)) {
+ return null;
+ } else if (Boolean.class.equals(boxedType)) {
+ return null;
+ } else {
+ throw new IllegalArgumentException("%s is not a boxed type!".formatted(boxedType));
+ }
+ }
+
+ public void addByte(byte value) {
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+
+ public void addShort(short value) {
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+
+ public void addInt(int value) {
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+
+ public void addLong(long value) {
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+
+ public void addFloat(float value) {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+
+ public void addDouble(double value) {
+ throw new UnsupportedOperationException("this list is not of type Double!");
+ }
+
+ public void addChar(char value) {
+ throw new UnsupportedOperationException("this list is not of type Character!");
+ }
+
+ public void addBoolean(boolean value) {
+ throw new UnsupportedOperationException("this list is not of type Boolean!");
+ }
+
+ public byte getByte(int index) {
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+
+ public short getShort(int index) {
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+
+ public int getInt(int index) {
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+
+ public long getLong(int index) {
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+
+ public float getFloat(int index) {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+
+ public double getDouble(int index) {
+ throw new UnsupportedOperationException("this list is not of type Double!");
+ }
+
+ public char getChar(int index) {
+ throw new UnsupportedOperationException("this list is not of type Character!");
+ }
+
+ public boolean getBoolean(int index) {
+ throw new UnsupportedOperationException("this list is not of type Boolean!");
+ }
+ public byte[] toByteArray() {
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+
+ public short[] toShortArray() {
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+
+ public int[] toIntArray() {
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+
+ public long[] toLongArray() {
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+
+ public float[] toFloatArray() {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+
+ public double[] toDoubleArray() {
+ throw new UnsupportedOperationException("this list is not of type Double!");
+ }
+
+ public char[] toCharArray() {
+ throw new UnsupportedOperationException("this list is not of type Character!");
+ }
+
+ public boolean[] toBooleanArray() {
+ throw new UnsupportedOperationException("this list is not of type Boolean!");
+ }
+
+ public byte[] finalizeAsByteArray() {
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+
+ public short[] finalizeAsShortArray() {
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+
+ public int[] finalizeAsIntArray() {
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+
+ public long[] finalizeAsLongArray() {
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+
+ public float[] finalizeAsFloatArray() {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+
+ public double[] finalizeAsDoubleArray() {
+ throw new UnsupportedOperationException("this list is not of type Double!");
+ }
+
+ public char[] finalizeAsCharArray() {
+ throw new UnsupportedOperationException("this list is not of type Character!");
+ }
+
+ public boolean[] finalizeAsBooleanArray() {
+ throw new UnsupportedOperationException("this list is not of type Boolean!");
+ }
+
+ public abstract boolean isFinalized();
+}
diff --git a/src/dev/asdf00/general/utils/list/internal/AbstractBaseList.java b/src/dev/asdf00/general/utils/list/internal/AbstractBaseList.java
new file mode 100644
index 0000000..2205115
--- /dev/null
+++ b/src/dev/asdf00/general/utils/list/internal/AbstractBaseList.java
@@ -0,0 +1,489 @@
+package dev.asdf00.general.utils.list.internal;
+
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public abstract class AbstractBaseList implements List {
+
+ static final Unsafe UNSAFE;
+ static final long OFFSET_LEN;
+
+ static {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ UNSAFE = (Unsafe) f.get(null);
+ // OFFSET_LEN = sizeof(mark-word) + sizeof(klass-ptr)
+ OFFSET_LEN = UNSAFE.addressSize() + (UNSAFE.addressSize() == 8 && System.getProperty("java.vm.compressedOopsMode") == null ? 8 : 4);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected int size;
+ protected int modCnt;
+
+ @Override
+ public Object[] toArray() {
+ return toArray(Object[]::new);
+ }
+
+ @Override
+ public T1[] toArray(T1[] a) {
+ return toArray(a, 0, size);
+ }
+
+ @Override
+ public int size() {
+ return size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() < 1;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return listIterator();
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ for (Object o : c) {
+ if (!contains(o)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public T remove(int index) {
+ Objects.checkIndex(index, size);
+ return remove(index, 0, size);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int index = indexOf(o);
+ if (index >= 0) {
+ remove(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ boolean changed = false;
+ for (Object o : c) {
+ changed = remove(o) || changed;
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ boolean changed = false;
+ ListIterator itr = listIterator();
+ while (itr.hasNext()) {
+ if (c.contains(itr.next())) {
+ itr.remove();
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return indexOf(o, 0, size);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return lastIndexOf(o, 0, size);
+ }
+
+ @Override
+ public T set(int index, T element) {
+ Objects.checkIndex(index, size);
+ return directSet(index, element);
+ }
+
+ @Override
+ public boolean add(T t) {
+ directSet(size++, t);
+ return true;
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return new ListItr<>(this, 0);
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ Objects.checkIndex(index, size);
+ return new ListItr<>(this, index);
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ Objects.checkIndex(fromIndex, size);
+ Objects.checkIndex(fromIndex, toIndex);
+ int len = (toIndex - fromIndex) + 1;
+ if (len < 0) {
+ throw new IllegalArgumentException();
+ }
+ return new SubList<>(this, fromIndex, len);
+ }
+
+ protected abstract T1[] toArray(T1[] a, int start, int len);
+
+ protected abstract T remove(Object o, int start, int len);
+
+ protected abstract int indexOf(Object o, int start, int len);
+
+ protected abstract int lastIndexOf(Object o, int start, int len);
+
+ protected abstract T directSet(int index, T element);
+
+ protected abstract void removeRange(int start, int len);
+
+
+ private static class ListItr implements ListIterator {
+
+ private final AbstractBaseList base;
+ private int modCnt;
+ private int cur;
+ private int last;
+
+ public ListItr(AbstractBaseList base, int start) {
+ this.base = base;
+ modCnt = base.modCnt;
+ cur = start;
+ last = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cur < base.size;
+ }
+
+ @Override
+ public E next() {
+ checkConcurrentModification();
+ if (!hasNext()) {
+ throw new IndexOutOfBoundsException();
+ }
+ last = cur;
+ return base.get(cur++);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return cur > 1;
+ }
+
+ @Override
+ public E previous() {
+ checkConcurrentModification();
+ if (!hasPrevious()) {
+ throw new IndexOutOfBoundsException();
+ }
+ last = --cur;
+ return base.get(cur);
+ }
+
+ @Override
+ public int nextIndex() {
+ return cur;
+ }
+
+ @Override
+ public int previousIndex() {
+ return cur - 1;
+ }
+
+ @Override
+ public void remove() {
+ checkConcurrentModification();
+ Objects.checkIndex(cur, base.size);
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.remove(--cur);
+ last = -1;
+ }
+
+ @Override
+ public void set(E e) {
+ checkConcurrentModification();
+ Objects.checkIndex(cur, base.size);
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.set(cur, e);
+ last = -1;
+ }
+
+ @Override
+ public void add(E e) {
+ checkConcurrentModification();
+ Objects.checkIndex(cur, base.size);
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.add(cur, e);
+ last = -1;
+ }
+
+ private void checkConcurrentModification() {
+ if (base.modCnt != modCnt) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+
+ private static class SubList extends AbstractBaseList {
+
+ private final AbstractBaseList base;
+ private final int start;
+
+ public SubList(AbstractBaseList base, int start, int size) {
+ this.base = base;
+ this.start = start;
+ this.size = size;
+ modCnt = base.modCnt;
+ }
+
+ @Override
+ public boolean addAll(Collection extends E> c) {
+ for (E e : c) {
+ add(e);
+ }
+ return c.size() > 0;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends E> c) {
+ Objects.checkIndex(index, size);
+ int i = 0;
+ for (E e : c) {
+ add(i, e);
+ }
+ return false;
+ }
+
+ @Override
+ public void clear() {
+ checkConcurrentModification();
+ modCnt++;
+ base.removeRange(start, size);
+ size = 0;
+ }
+
+ @Override
+ public E get(int index) {
+ checkConcurrentModification();
+ Objects.checkIndex(index, size);
+ return base.get(start + index);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ checkConcurrentModification();
+ Objects.checkIndex(index, size);
+ modCnt++;
+ base.add(start + index, element);
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return new SubListItr<>(base, start, start, start + (size - 1));
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ Objects.checkIndex(index, size);
+ return new SubListItr<>(base, start + index, start, start + (size - 1));
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ checkConcurrentModification();
+ Objects.checkIndex(fromIndex, size);
+ Objects.checkIndex(toIndex, size);
+ int len = (toIndex - fromIndex) + 1;
+ if (len < 0) {
+ throw new IllegalArgumentException();
+ }
+ return new SubList<>(base, start + fromIndex, len);
+ }
+
+ @Override
+ protected T1[] toArray(T1[] a, int start, int len) {
+ checkConcurrentModification();
+ modCnt++;
+ return base.toArray(a, this.start + start, len);
+ }
+
+ @Override
+ protected E remove(Object o, int start, int len) {
+ checkConcurrentModification();
+ modCnt++;
+ return base.remove(o, this.start + start, len);
+ }
+
+ @Override
+ protected int indexOf(Object o, int start, int len) {
+ checkConcurrentModification();
+ return base.indexOf(o, this.start + start, len);
+ }
+
+ @Override
+ protected int lastIndexOf(Object o, int start, int len) {
+ checkConcurrentModification();
+ return base.lastIndexOf(o, this.start + start, len);
+ }
+
+ @Override
+ protected E directSet(int index, E element) {
+ checkConcurrentModification();
+ modCnt++;
+ return base.directSet(index, element);
+ }
+
+ @Override
+ protected void removeRange(int start, int len) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void checkConcurrentModification() {
+ if (base.modCnt != modCnt) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+
+ private static class SubListItr implements ListIterator {
+
+ private final AbstractBaseList base;
+ private int modCnt;
+ private int cur;
+ private int lower;
+ private int higher;
+ private int last;
+
+ public SubListItr(AbstractBaseList base, int start, int lower, int higher) {
+ this.base = base;
+ modCnt = base.modCnt;
+ cur = start;
+ this.lower = lower;
+ this.higher = higher;
+ last = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cur <= higher;
+ }
+
+ @Override
+ public TYPE next() {
+ checkConcurrentModification();
+ if (!hasNext()) {
+ throw new IndexOutOfBoundsException();
+ }
+ last = cur;
+ return base.get(cur++);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return cur > lower;
+ }
+
+ @Override
+ public TYPE previous() {
+ checkConcurrentModification();
+ if (!hasPrevious()) {
+ throw new IndexOutOfBoundsException();
+ }
+ last = --cur;
+ return base.get(cur);
+ }
+
+ @Override
+ public int nextIndex() {
+ return cur - lower;
+ }
+
+ @Override
+ public int previousIndex() {
+ return cur - lower - 1;
+ }
+
+ @Override
+ public void remove() {
+ checkConcurrentModification();
+ rangeCheck();
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.remove(last);
+ last = -1;
+ }
+
+ @Override
+ public void set(TYPE element) {
+ checkConcurrentModification();
+ rangeCheck();
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.set(last, element);
+ last = -1;
+ }
+
+ @Override
+ public void add(TYPE element) {
+ checkConcurrentModification();
+ rangeCheck();
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ modCnt++;
+ base.add(last, element);
+ last = -1;
+ }
+
+ private void checkConcurrentModification() {
+ if (base.modCnt != modCnt) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private void rangeCheck() {
+ if (cur < lower || cur > higher) {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/dev/asdf00/general/utils/list/internal/ByteList.java b/src/dev/asdf00/general/utils/list/internal/ByteList.java
new file mode 100644
index 0000000..2567f85
--- /dev/null
+++ b/src/dev/asdf00/general/utils/list/internal/ByteList.java
@@ -0,0 +1,97 @@
+package dev.asdf00.general.utils.list.internal;
+
+import dev.asdf00.general.utils.list.PrimitiveList;
+
+import java.util.Collection;
+
+public class ByteList extends PrimitiveList {
+
+ private byte[] data;
+
+ public ByteList(int initial) {
+
+ }
+
+ @Override
+ public boolean isFinalized() {
+ return data == null;
+ }
+
+ @Override
+ protected T1[] toArray(T1[] a, int start, int len) {
+ return null;
+ }
+
+ @Override
+ protected Boolean remove(Object o, int start, int len) {
+ return null;
+ }
+
+ @Override
+ protected int indexOf(Object o, int start, int len) {
+ return 0;
+ }
+
+ @Override
+ protected int lastIndexOf(Object o, int start, int len) {
+ return 0;
+ }
+
+ @Override
+ protected Boolean directSet(int index, Boolean element) {
+ return null;
+ }
+
+ @Override
+ protected void removeRange(int start, int len) {
+
+ }
+
+ @Override
+ public boolean addAll(Collection extends Boolean> c) {
+ return false;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends Boolean> c) {
+ return false;
+ }
+
+ @Override
+ public void clear() {
+
+ }
+
+ @Override
+ public Boolean get(int index) {
+ return null;
+ }
+
+ @Override
+ public void add(int index, Boolean element) {
+
+ }
+
+ @Override
+ public void addByte(byte value) {
+
+ }
+
+ @Override
+ public byte getByte(int index) {
+ return 0;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return new byte[0];
+ }
+
+ @Override
+ public byte[] finalizeAsByteArray() {
+ byte[] res = data;
+ data = null;
+ AbstractBaseList.UNSAFE.putInt(data, AbstractBaseList.OFFSET_LEN, size);
+ return res;
+ }
+}
diff --git a/src/dev/asdf00/general/utils/listOld/PrimitiveList.java b/src/dev/asdf00/general/utils/listOld/PrimitiveList.java
new file mode 100644
index 0000000..53b7549
--- /dev/null
+++ b/src/dev/asdf00/general/utils/listOld/PrimitiveList.java
@@ -0,0 +1,79 @@
+package dev.asdf00.general.utils.listOld;
+
+import dev.asdf00.general.utils.listOld.internal.PrimitiveListImpl;
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.RandomAccess;
+
+public abstract class PrimitiveList implements List, RandomAccess {
+
+ private static final Unsafe UNSAFE;
+
+ static {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ UNSAFE = (Unsafe) f.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static boolean isSupportedOnCurrentJVMConfiguration() {
+ return UNSAFE.arrayIndexScale(byte[].class) == 1 && UNSAFE.arrayIndexScale(short[].class) == 2 &&
+ UNSAFE.arrayIndexScale(int[].class) == 4 && UNSAFE.arrayIndexScale(long[].class) == 8 &&
+ UNSAFE.arrayIndexScale(float[].class) == 4 && UNSAFE.arrayIndexScale(double[].class) == 8;
+ }
+
+ public static PrimitiveList create(Class boxedType) throws IllegalArgumentException, UnsupportedOperationException {
+ return PrimitiveListImpl.create(boxedType);
+ }
+
+ public abstract byte[] toByteArray();
+
+ public abstract short[] toShortArray();
+
+ public abstract int[] toIntArray();
+
+ public abstract long[] toLongArray();
+
+ public abstract float[] toFloatArray();
+
+ public abstract double[] toDoubleArray();
+
+ public abstract char[] toCharArray();
+
+ public abstract boolean[] toBooleanArray();
+
+ public abstract byte getByte(int index);
+
+ public abstract short getShort(int index);
+
+ public abstract int getInt(int index);
+
+ public abstract long getLong(int index);
+
+ public abstract float getFloat(int index);
+
+ public abstract double getDouble(int index);
+
+ public abstract char getChar(int index);
+
+ public abstract boolean getBoolean(int index);
+
+ public abstract byte[] finalizeAsByteArray();
+
+ public abstract short[] finalizeAsShortArray();
+
+ public abstract int[] finalizeAsIntArray();
+
+ public abstract long[] finalizeAsLongArray();
+
+ public abstract float[] finalizeAsFloatArray();
+
+ public abstract double[] finalizeAsDoubleArray();
+
+ public abstract boolean isFinalized();
+}
diff --git a/src/dev/asdf00/general/utils/listOld/internal/PrimitiveListImpl.java b/src/dev/asdf00/general/utils/listOld/internal/PrimitiveListImpl.java
new file mode 100644
index 0000000..cd0044e
--- /dev/null
+++ b/src/dev/asdf00/general/utils/listOld/internal/PrimitiveListImpl.java
@@ -0,0 +1,1218 @@
+package dev.asdf00.general.utils.listOld.internal;
+
+import dev.asdf00.general.utils.listOld.PrimitiveList;
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public final class PrimitiveListImpl extends PrimitiveList {
+
+ private static final Unsafe UNSAFE;
+ private static final long OFFSET;
+ private static final int KLASS_WORD_OFFSET;
+ private static final int KLASS_WORD_SIZE;
+ private static final int LENGTH_OFFSET;
+
+ static {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ UNSAFE = (Unsafe) f.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ OFFSET = UNSAFE.arrayBaseOffset(long[].class);
+ KLASS_WORD_OFFSET = UNSAFE.addressSize();
+ KLASS_WORD_SIZE = UNSAFE.addressSize() == 4 || System.getProperty("java.vm.compressedOopsMode") != null ? 4 : 8;
+ LENGTH_OFFSET = KLASS_WORD_OFFSET + KLASS_WORD_SIZE;
+ }
+
+
+ private long[] rawData;
+ private int size;
+ private int modCount = 0;
+ private int type;
+
+ private PrimitiveListImpl(int type) {
+ this.type = type;
+ rawData = new long[16 >> (0xFF & (type >> 16))];
+ size = 0;
+ }
+
+ public static PrimitiveListImpl create(Class boxedType) throws UnsupportedOperationException {
+ if (!isSupportedOnCurrentJVMConfiguration()) {
+ throw new UnsupportedOperationException("this list is not supported with your current JVM settings due to a mismatch in array index scales!");
+ }
+ int type;
+ if (Byte.class.equals(boxedType)) {
+ type = 0x03_01_00;
+ } else if (Short.class.equals(boxedType)) {
+ type = 0x02_02_01;
+ } else if (Integer.class.equals(boxedType)) {
+ type = 0x01_04_02;
+ } else if (Long.class.equals(boxedType)) {
+ type = 0x00_08_03;;
+ } else if (Float.class.equals(boxedType)) {
+ type = 0x01_04_04;
+ } else if (Double.class.equals(boxedType)) {
+ type = 0x00_08_05;
+ } else if (Character.class.equals(boxedType)) {
+ type = 0x01_04_06;
+ } else if (Boolean.class.equals(boxedType)) {
+ type = 0x03_01_07;
+ } else {
+ throw new IllegalArgumentException("%s is not a boxed type!".formatted(boxedType));
+ }
+ return new PrimitiveListImpl<>(type);
+ }
+
+
+ @Override
+ public boolean isFinalized() {
+ return type == -1;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size < 1;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return listIterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toArray(Object[]::new);
+ }
+
+ @Override
+ public T1[] toArray(T1[] a) {
+ return toArray(a, 0, size);
+ }
+
+ @Override
+ public boolean add(T t) {
+ increaseSize(1);
+ directSet(size - 1, t);
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int index = indexOf(o);
+ if (index >= 0) {
+ remove(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ BitSet checked = new BitSet(c.size());
+ int i;
+ for (T element : this) {
+ i = 0;
+ for (Object inner : c) {
+ if (element.equals(inner)) {
+ checked.set(i);
+ }
+ }
+ }
+ for (i = 0; i < c.size(); i++) {
+ if (!checked.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection extends T> c) {
+ int i = size;
+ increaseSize(c.size());
+ for (T element : c) {
+ directSet(i++, element);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends T> c) {
+ Objects.checkIndex(index, size);
+ increaseSize(c.size());
+ openGap(index, c.size());
+ int i = index;
+ for (T element : c) {
+ directSet(i, element);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ for (int i = 0; i < size; i++) {
+ if (c.contains(get(i))) {
+ remove(i);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ for (int i = 0; i < size; i++) {
+ if (!c.contains(get(i))) {
+ remove(i);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void clear() {
+ checkFinalized();
+ modCount++;
+ size = 0;
+ rawData = new long[16 >> (0xFF & (type >> 16))];
+ }
+
+ @Override
+ public T get(int index) {
+ Objects.checkIndex(index, size);
+ switch (0xFF & type) {
+ case 0:
+ return (T) Byte.valueOf(UNSAFE.getByte(rawData, OFFSET + index));
+ case 1:
+ return (T) Short.valueOf(UNSAFE.getShort(rawData, OFFSET + (index << 1)));
+ case 2:
+ return (T) Integer.valueOf(UNSAFE.getInt(rawData, OFFSET + (index << 2)));
+ case 3:
+ return (T) Long.valueOf(UNSAFE.getLong(rawData, OFFSET + (index << 3)));
+ case 4:
+ return (T) Float.valueOf(UNSAFE.getFloat(rawData, OFFSET + (index << 2)));
+ case 5:
+ return (T) Double.valueOf(UNSAFE.getDouble(rawData, OFFSET + (index << 3)));
+ case 6:
+ return (T) Character.valueOf((char) UNSAFE.getInt(rawData, OFFSET + (index << 2)));
+ case 7:
+ return (T) Boolean.valueOf(UNSAFE.getByte(rawData, OFFSET + index) != 0);
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ }
+
+ @Override
+ public T set(int index, T element) {
+ Objects.checkIndex(index, size);
+ T prev = get(index);
+ directSet(index, element);
+ return prev;
+ }
+
+ @Override
+ public void add(int index, T element) {
+ Objects.checkIndex(index, size);
+ increaseSize(1);
+ openGap(index, 1);
+ directSet(index, element);
+ }
+
+ @Override
+ public T remove(int index) {
+ Objects.checkIndex(index, size);
+ T removed = get(index);
+ fillGap(index, 1);
+ size--;
+ return removed;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return indexOf(o, 0, size);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return lastIndexOf(o, 0, size);
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return new ListItr<>(this, 0);
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ Objects.checkIndex(index, size);
+ return new ListItr<>(this, index);
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ Objects.checkIndex(fromIndex, size);
+ Objects.checkIndex(toIndex, size);
+ checkFinalized();
+ if (fromIndex > toIndex) {
+ throw new IllegalArgumentException();
+ }
+ return new SubList<>(this, fromIndex, toIndex);
+ }
+
+ //======================================================
+ // additional primitive access points
+ //======================================================
+ @Override
+ public byte[] toByteArray() {
+ checkFinalized();
+ int shift = 3 - (0xFF & (type >> 16));
+ int targetSize = size << shift;
+ byte[] result = new byte[targetSize];
+ UNSAFE.copyMemory(rawData, OFFSET, result, UNSAFE.arrayBaseOffset(byte[].class), targetSize);
+ return result;
+ }
+
+ @Override
+ public short[] toShortArray() {
+ checkFinalized();
+ int shift = 2 - (0xFF & (type >> 16));
+ if (shift < 0) {
+ throw new UnsupportedOperationException("cannot transform this into short[]");
+ }
+ int targetSize = size << shift;
+ short[] result = new short[targetSize];
+ UNSAFE.copyMemory(rawData, OFFSET, result, UNSAFE.arrayBaseOffset(short[].class), targetSize << 1);
+ return result;
+ }
+
+ @Override
+ public int[] toIntArray() {
+ checkFinalized();
+ int shift = 1 - (0xFF & (type >> 16));
+ if (shift < 0) {
+ throw new UnsupportedOperationException("cannot transform this into int[]");
+ }
+ int targetSize = size << shift;
+ int[] result = new int[targetSize];
+ UNSAFE.copyMemory(rawData, OFFSET, result, UNSAFE.arrayBaseOffset(int[].class), targetSize << 2);
+ return result;
+ }
+
+ @Override
+ public long[] toLongArray() {
+ checkFinalized();
+ if ((0xFF & (type >> 16)) != 0) {
+ throw new UnsupportedOperationException("cannot transform this into long[]");
+ }
+ return Arrays.copyOf(rawData, size);
+ }
+
+ @Override
+ public float[] toFloatArray() {
+ checkFinalized();
+ int shift = 1 - (0xFF & (type >> 16));
+ if (shift < 0) {
+ throw new UnsupportedOperationException("cannot this transform into float[]");
+ }
+ int targetSize = size << shift;
+ float[] result = new float[targetSize];
+ UNSAFE.copyMemory(rawData, OFFSET, result, UNSAFE.arrayBaseOffset(float[].class), size << 2);
+ return result;
+ }
+
+ @Override
+ public double[] toDoubleArray() {
+ checkFinalized();
+ if ((0xFF & (type >> 16)) != 0) {
+ throw new UnsupportedOperationException("cannot transform this into double[]");
+ }
+ double[] result = new double[size];
+ UNSAFE.copyMemory(rawData, OFFSET, result, UNSAFE.arrayBaseOffset(byte[].class), size << 3);
+ return result;
+ }
+
+ @Override
+ public char[] toCharArray() {
+ checkFinalized();
+ int shift = 1 - (0xFF & (type >> 16));
+ if (shift < 0) {
+ throw new UnsupportedOperationException("cannot transform this into char[]");
+ }
+ int targetSize = size << shift;
+ char[] result = new char[targetSize];
+ for (int i = 0; i < targetSize; i++) {
+ result[i] = (char) UNSAFE.getInt(rawData, OFFSET + (i << 2));
+ }
+ return result;
+ }
+
+ @Override
+ public boolean[] toBooleanArray() {
+ checkFinalized();
+ int shift = 3 - (0xFF & (type >> 16));
+ int targetSize = size << shift;
+ boolean[] result = new boolean[targetSize];
+ for (int i = 0; i < targetSize; i++) {
+ result[i] = UNSAFE.getByte(rawData, OFFSET + i) != 0;
+ }
+ return result;
+ }
+
+ @Override
+ public byte getByte(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 0) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+ return UNSAFE.getByte(rawData, OFFSET + index);
+ }
+
+ @Override
+ public short getShort(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 1) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+ return UNSAFE.getShort(rawData, OFFSET + (index << 1));
+ }
+
+ @Override
+ public int getInt(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 2) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+ return UNSAFE.getInt(rawData, OFFSET + (index << 2));
+ }
+
+ @Override
+ public long getLong(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 3) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+ return UNSAFE.getLong(rawData, OFFSET + (index << 3));
+ }
+
+ @Override
+ public float getFloat(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 4) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+ return UNSAFE.getFloat(rawData, OFFSET + (index << 2));
+ }
+
+ @Override
+ public double getDouble(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 5) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Double!");
+ }
+ return UNSAFE.getDouble(rawData, OFFSET + (index << 3));
+ }
+
+ @Override
+ public char getChar(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 6) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Character!");
+ }
+ return (char) UNSAFE.getInt(rawData, OFFSET + (index << 2));
+ }
+
+ @Override
+ public boolean getBoolean(int index) {
+ Objects.checkIndex(index, size);
+ if ((0xFF & type) != 7) {
+ checkFinalized();
+ throw new UnsupportedOperationException("this list is not of type Boolean!");
+ }
+ return UNSAFE.getByte(rawData, OFFSET + index) != 0;
+ }
+
+ @Override
+ public byte[] finalizeAsByteArray() {
+ checkFinalized();
+ if ((0xFF & type) != 0) {
+ throw new UnsupportedOperationException("this list is not of type Byte!");
+ }
+ rewriteArrayHeader(new byte[0]);
+ return (byte[]) (Object) rawData;
+ }
+
+ @Override
+ public short[] finalizeAsShortArray() {
+ checkFinalized();
+ if ((0xFF & type) != 1) {
+ throw new UnsupportedOperationException("this list is not of type Short!");
+ }
+ rewriteArrayHeader(new short[0]);
+ return (short[]) (Object) rawData;
+ }
+
+ @Override
+ public int[] finalizeAsIntArray() {
+ checkFinalized();
+ if ((0xFF & type) != 2) {
+ throw new UnsupportedOperationException("this list is not of type Integer!");
+ }
+ rewriteArrayHeader(new int[0]);
+ return (int[]) (Object) rawData;
+ }
+
+ @Override
+ public long[] finalizeAsLongArray() {
+ checkFinalized();
+ if ((0xFF & type) != 3) {
+ throw new UnsupportedOperationException("this list is not of type Long!");
+ }
+ rewriteArrayHeader(new long[0]);
+ return rawData;
+ }
+
+ @Override
+ public float[] finalizeAsFloatArray() {
+ checkFinalized();
+ if ((0xFF & type) != 4) {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+ rewriteArrayHeader(new float[0]);
+ return (float[]) (Object) rawData;
+ }
+
+ @Override
+ public double[] finalizeAsDoubleArray() {
+ checkFinalized();
+ if ((0xFF & type) != 5) {
+ throw new UnsupportedOperationException("this list is not of type Float!");
+ }
+ rewriteArrayHeader(new double[0]);
+ return (double[]) (Object) rawData;
+ }
+
+ //======================================================
+ // private helper methods
+ //======================================================
+ private void rewriteArrayHeader(Object emptyArrayInstance) {
+ type = -1;
+ if (KLASS_WORD_SIZE == 4) {
+ UNSAFE.putInt(rawData, KLASS_WORD_OFFSET, UNSAFE.getInt(emptyArrayInstance, KLASS_WORD_OFFSET));
+ } else {
+ UNSAFE.putLong(rawData, KLASS_WORD_OFFSET, UNSAFE.getLong(emptyArrayInstance, KLASS_WORD_OFFSET));
+ }
+ UNSAFE.putInt(rawData, LENGTH_OFFSET, size);
+ }
+
+ private void checkFinalized() {
+ if (type == -1) {
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ }
+
+ private void increaseSize(int by) {
+ checkFinalized();
+ if (Integer.MAX_VALUE - by < size) {
+ throw new IllegalStateException("size reached integer overflow!");
+ }
+ int shiftBy = type >> 16;
+ // shiftBy gets implicitly masked to 0x1F
+ int capacity = rawData.length << shiftBy;
+ size += by;
+ if (capacity < size) {
+ capacity = Integer.highestOneBit(size);
+ if (capacity != size) {
+ capacity <<= 1;
+ }
+ rawData = Arrays.copyOf(rawData, capacity >> shiftBy);
+ }
+ }
+
+ private void directSet(int index, T element) {
+ modCount++;
+ switch (0xFF & type) {
+ case 0:
+ UNSAFE.putByte(rawData, OFFSET + index, ((Byte) element).byteValue());
+ return;
+ case 1:
+ UNSAFE.putShort(rawData, OFFSET + (index << 1), ((Short) element).shortValue());
+ return;
+ case 2:
+ UNSAFE.putInt(rawData, OFFSET + (index << 2), ((Integer) element).intValue());
+ return;
+ case 3:
+ UNSAFE.putLong(rawData, OFFSET + (index << 3), ((Long) element).longValue());
+ return;
+ case 4:
+ UNSAFE.putFloat(rawData, OFFSET + (index << 2), ((Float) element).floatValue());
+ return;
+ case 5:
+ UNSAFE.putDouble(rawData, OFFSET + (index << 3), ((Double) element).doubleValue());
+ return;
+ case 6:
+ UNSAFE.putInt(rawData, OFFSET + (index << 2), ((Character) element).charValue());
+ return;
+ case 7:
+ UNSAFE.putByte(rawData, OFFSET + index, ((Boolean) element) ? (byte) 1 : (byte) 0);
+ return;
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ }
+
+ private void fillGap(int at, int gapSize) {
+ modCount++;
+ switch (0xFF & (type >> 16)) {
+ case 3: // byte sized elements
+ for (int i = at; i + gapSize < size; i++) {
+ UNSAFE.putByte(rawData, OFFSET + i, UNSAFE.getByte(rawData, OFFSET + i + gapSize));
+ }
+ break;
+ case 2: // short sized elements
+ for (int i = at; i + gapSize < size; i++) {
+ UNSAFE.putShort(rawData, OFFSET + (i << 1), UNSAFE.getShort(rawData, OFFSET + ((i + gapSize) << 1)));
+ }
+ break;
+ case 1: // int sized elements
+ for (int i = at; i + gapSize < size; i++) {
+ UNSAFE.putInt(rawData, OFFSET + (i << 2), UNSAFE.getInt(rawData, OFFSET + ((i + gapSize) << 2)));
+ }
+ break;
+ case 0: // long sized elements
+ for (int i = at; i + gapSize < size; i++) {
+ UNSAFE.putLong(rawData, OFFSET + (i << 3), UNSAFE.getLong(rawData, OFFSET + ((i + gapSize) << 3)));
+ }
+ break;
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ }
+
+ private void openGap(int at, int gapSize) {
+ modCount++;
+ switch (0xFF & (type >> 16)) {
+ case 3: // byte sized elements
+ for (int i = size - 1; i - gapSize >= at; i--) {
+ UNSAFE.putByte(rawData, OFFSET + i, UNSAFE.getByte(rawData, OFFSET + i - gapSize));
+ }
+ break;
+ case 2: // short sized elements
+ for (int i = size - 1; i - gapSize >= at; i--) {
+ UNSAFE.putShort(rawData, OFFSET + (i << 1), UNSAFE.getShort(rawData, OFFSET + ((i - gapSize) << 1)));
+ }
+ break;
+ case 1: // int sized elements
+ for (int i = size - 1; i - gapSize >= at; i--) {
+ UNSAFE.putInt(rawData, OFFSET + (i << 2), UNSAFE.getInt(rawData, OFFSET + ((i - gapSize) << 2)));
+ }
+ break;
+ case 0: // long sized elements
+ for (int i = size - 1; i - gapSize >= at; i--) {
+ UNSAFE.putLong(rawData, OFFSET + (i << 3), UNSAFE.getLong(rawData, OFFSET + ((i - gapSize) << 3)));
+ }
+ break;
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ }
+
+ private T1[] toArray(T1[] a, int from, int to) {
+ Object[] dest = Arrays.copyOf(a, to - from, a.getClass());
+ switch (0xFF & type) {
+ case 0:
+ for (int i = from; i < to; i++) {
+ dest[i] = Byte.valueOf(UNSAFE.getByte(rawData, OFFSET + i));
+ }
+ break;
+ case 1:
+ for (int i = from; i < to; i++) {
+ dest[i] = Short.valueOf(UNSAFE.getShort(rawData, OFFSET + i * 2));
+ }
+ break;
+ case 2:
+ for (int i = from; i < to; i++) {
+ dest[i] = Integer.valueOf(UNSAFE.getInt(rawData, OFFSET + i * 4));
+ }
+ break;
+ case 3:
+ for (int i = from; i < to; i++) {
+ dest[i] = Long.valueOf(UNSAFE.getLong(rawData, OFFSET + i * 8));
+ }
+ break;
+ case 4:
+ for (int i = from; i < to; i++) {
+ dest[i] = Float.valueOf(UNSAFE.getFloat(rawData, OFFSET + i * 4));
+ }
+ break;
+ case 5:
+ for (int i = from; i < to; i++) {
+ dest[i] = Double.valueOf(UNSAFE.getDouble(rawData, OFFSET + i * 8));
+ }
+ break;
+ case 6:
+ for (int i = from; i < to; i++) {
+ dest[i] = Character.valueOf((char) UNSAFE.getInt(rawData, OFFSET + i * 4));
+ }
+ break;
+ case 7:
+ for (int i = from; i < to; i++) {
+ dest[i] = Boolean.valueOf(UNSAFE.getByte(rawData, OFFSET + i) == 1);
+ }
+ break;
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ return (T1[]) dest;
+ }
+
+ private int indexOf(Object o, int from, int to) {
+ switch (0xFF & type) {
+ case 0: {
+ byte target = ((Byte) o).byteValue();
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getByte(rawData, OFFSET + i)) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 1: {
+ short target = ((Short) o).shortValue();
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getShort(rawData, OFFSET + (i << 1))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 2: {
+ int target = ((Integer) o).intValue();
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getInt(rawData, OFFSET + (i << 2))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 3: {
+ long target = ((Long) o).longValue();
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getLong(rawData, OFFSET + (i << 3))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 4: {
+ float target = ((Float) o).floatValue();
+ for (int i = from; i < to; i++) {
+ if (Float.compare(target, UNSAFE.getFloat(rawData, OFFSET + (i << 2))) == 0) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 5: {
+ double target = ((Double) o).doubleValue();
+ for (int i = from; i < to; i++) {
+ if (Double.compare(target, UNSAFE.getDouble(rawData, OFFSET + (i << 3))) == 0) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 6: {
+ int target = ((Character) o).charValue();
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getInt(rawData, OFFSET + (i << 2))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 7: {
+ byte target = ((Boolean) o) ? (byte) 1 : (byte) 0;
+ for (int i = from; i < to; i++) {
+ if (target == UNSAFE.getByte(rawData, OFFSET + i)) {
+ return i;
+ }
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ return -1;
+ }
+
+ private int lastIndexOf(Object o, int from, int to) {
+ switch (0xFF & type) {
+ case 0: {
+ byte target = ((Byte) o).byteValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getByte(rawData, OFFSET + i)) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 1: {
+ short target = ((Short) o).shortValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getShort(rawData, OFFSET + (i << 1))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 2: {
+ int target = ((Integer) o).intValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getInt(rawData, OFFSET + (i << 2))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 3: {
+ long target = ((Long) o).longValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getLong(rawData, OFFSET + (i << 3))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 4: {
+ float target = ((Float) o).floatValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (Float.compare(target, UNSAFE.getFloat(rawData, OFFSET + (i << 2))) == 0) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 5: {
+ double target = ((Double) o).doubleValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (Double.compare(target, UNSAFE.getDouble(rawData, OFFSET + (i << 3))) == 0) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 6: {
+ int target = ((Character) o).charValue();
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getInt(rawData, OFFSET + (i << 2))) {
+ return i;
+ }
+ }
+ break;
+ }
+ case 7: {
+ byte target = ((Boolean) o) ? (byte) 1 : (byte) 0;
+ for (int i = to - 1; i >= from; i--) {
+ if (target == UNSAFE.getByte(rawData, OFFSET + i)) {
+ return i;
+ }
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ return -1;
+ }
+
+ //======================================================
+ // internal classes
+ //======================================================
+ private static class ListItr implements ListIterator {
+ private final PrimitiveListImpl parent;
+ private int cur;
+ private int expectedModCount;
+
+ public ListItr(PrimitiveListImpl parent, int startingAt) {
+ if (parent.type == -1) {
+ throw new IllegalStateException("this list has been finalized!");
+ }
+ this.parent = parent;
+ cur = startingAt;
+ expectedModCount = parent.modCount;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cur < parent.size;
+ }
+
+ @Override
+ public E next() {
+ checkForConcurrentModification();
+ return parent.get(cur++);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return cur > 0;
+ }
+
+ @Override
+ public E previous() {
+ checkForConcurrentModification();
+ return parent.get(--cur);
+ }
+
+ @Override
+ public int nextIndex() {
+ return cur;
+ }
+
+ @Override
+ public int previousIndex() {
+ return cur - 1;
+ }
+
+ @Override
+ public void remove() {
+ checkForConcurrentModification();
+ parent.remove(cur);
+ expectedModCount++;
+ }
+
+ @Override
+ public void set(E e) {
+ checkForConcurrentModification();
+ parent.set(cur, e);
+ expectedModCount++;
+ }
+
+ @Override
+ public void add(E e) {
+ checkForConcurrentModification();
+ parent.add(cur, e);
+ expectedModCount += 2;
+ }
+
+ private void checkForConcurrentModification() {
+ if (parent.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+
+ private static class SubList implements List {
+ private final PrimitiveListImpl baseList;
+ private final int start;
+ private int to;
+ private int expectedModCount;
+
+ public SubList(PrimitiveListImpl baseList, int start, int to) {
+ this.baseList = baseList;
+ this.start = start;
+ this.to = to;
+ expectedModCount = baseList.modCount;
+ }
+
+ @Override
+ public int size() {
+ return to - start;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() < 1;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ checkForConcurrentModification();
+ return indexOf(o) >= 0;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return listIterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toArray(Object[]::new);
+ }
+
+ @Override
+ public T[] toArray(T[] a) {
+ checkForConcurrentModification();
+ return baseList.toArray(a, start, to);
+ }
+
+ @Override
+ public boolean add(E e) {
+ checkForConcurrentModification();
+ expectedModCount += 2;
+ baseList.add(to, e);
+ to++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ checkForConcurrentModification();
+ int index = indexOf(o);
+ if (index >= 0) {
+ remove(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ checkForConcurrentModification();
+ BitSet checked = new BitSet(c.size());
+ int i;
+ for (E element : this) {
+ i = 0;
+ for (Object inner : c) {
+ if (element.equals(inner)) {
+ checked.set(i);
+ }
+ }
+ }
+ for (i = 0; i < c.size(); i++) {
+ if (!checked.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection extends E> c) {
+ checkForConcurrentModification();
+ expectedModCount += 1 + c.size();
+ baseList.addAll(to, c);
+ to += c.size();
+ return true;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends E> c) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ expectedModCount += 1 + c.size();
+ baseList.addAll(start + index, c);
+ to += c.size();
+ return true;
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ checkForConcurrentModification();
+ for (int i = 0; i < size(); i++) {
+ if (c.contains(get(i))) {
+ remove(i);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ for (int i = 0; i < size(); i++) {
+ if (!c.contains(get(i))) {
+ remove(i);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void clear() {
+ checkForConcurrentModification();
+ baseList.fillGap(start, size());
+ baseList.size -= size();
+ expectedModCount++;
+ to = start;
+ }
+
+ @Override
+ public E get(int index) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ return get(start + index);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ expectedModCount++;
+ return baseList.set(start + index, element);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ expectedModCount += 2;
+ baseList.add(start, element);
+ }
+
+ @Override
+ public E remove(int index) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ expectedModCount++;
+ E result = baseList.get(start + index);
+ baseList.remove(start + index);
+ return result;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ checkForConcurrentModification();
+ return baseList.indexOf(o, start, to);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ checkForConcurrentModification();
+ return baseList.lastIndexOf(o, start, to);
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ checkForConcurrentModification();
+ return new InnerIterator<>(this, start);
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ Objects.checkIndex(index, size());
+ checkForConcurrentModification();
+ return new InnerIterator<>(this, start + index);
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ if (fromIndex > toIndex) {
+ throw new IllegalArgumentException();
+ }
+ Objects.checkIndex(fromIndex, size());
+ Objects.checkIndex(toIndex, size());
+ checkForConcurrentModification();
+ return new SubList<>(baseList, start + fromIndex, start + fromIndex + toIndex);
+ }
+
+ private void checkForConcurrentModification() {
+ if (baseList.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private static class InnerIterator implements ListIterator {
+ private final SubList parent;
+ private int cur;
+ private int expectedModCount;
+
+ public InnerIterator(SubList parent, int startingAtBase) {
+ this.parent = parent;
+ cur = startingAtBase;
+ expectedModCount = parent.expectedModCount;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cur < parent.to;
+ }
+
+ @Override
+ public E next() {
+ checkBounds(cur);
+ checkForConcurrentModification();
+ return parent.baseList.get(cur++);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return cur > parent.start;
+ }
+
+ @Override
+ public E previous() {
+ checkBounds(cur);
+ checkForConcurrentModification();
+ return parent.baseList.get(--cur);
+ }
+
+ @Override
+ public int nextIndex() {
+ return cur;
+ }
+
+ @Override
+ public int previousIndex() {
+ return cur - 1;
+ }
+
+ @Override
+ public void remove() {
+ checkBounds(cur);
+ checkForConcurrentModification();
+ expectedModCount++;
+ parent.baseList.remove(cur);
+ }
+
+ @Override
+ public void set(E e) {
+ checkBounds(cur);
+ checkForConcurrentModification();
+ expectedModCount++;
+ parent.baseList.set(cur, e);
+ }
+
+ @Override
+ public void add(E e) {
+ checkBounds(cur);
+ checkForConcurrentModification();
+ expectedModCount += 2;
+ parent.baseList.add(cur, e);
+ }
+
+ private void checkForConcurrentModification() {
+ if (parent.baseList.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private void checkBounds(int index) {
+ if (index < parent.start || index >= parent.to) {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/module-info.java b/src/module-info.java
new file mode 100644
index 0000000..f003344
--- /dev/null
+++ b/src/module-info.java
@@ -0,0 +1,5 @@
+module GeneralUtils {
+ requires jdk.unsupported;
+ exports dev.asdf00.general.utils.listOld;
+ exports dev.asdf00.general.utils.list;
+}
\ No newline at end of file