diff --git a/pom.xml b/pom.xml
index b56a169..262429d 100755
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.moparisthebest
filelists
- 0.0.1
+ 0.1-SNAPSHOT
jar
filelists
diff --git a/src/main/java/com/moparisthebest/filelist/ByteArrayConverter.java b/src/main/java/com/moparisthebest/filelist/ByteArrayConverter.java
index 8096536..4e221f2 100644
--- a/src/main/java/com/moparisthebest/filelist/ByteArrayConverter.java
+++ b/src/main/java/com/moparisthebest/filelist/ByteArrayConverter.java
@@ -5,6 +5,6 @@ package com.moparisthebest.filelist;
*/
public interface ByteArrayConverter {
int numBytes();
- T fromBytes(final byte[] buff);
- void toBytes(final T o, final byte[] buff);
+ T fromBytes(final byte[] buff, final int off);
+ void toBytes(final T o, final byte[] buff, final int off);
}
diff --git a/src/main/java/com/moparisthebest/filelist/LongConverter40Bit.java b/src/main/java/com/moparisthebest/filelist/LongConverter40Bit.java
index 2c4410a..8e8abaf 100644
--- a/src/main/java/com/moparisthebest/filelist/LongConverter40Bit.java
+++ b/src/main/java/com/moparisthebest/filelist/LongConverter40Bit.java
@@ -16,20 +16,22 @@ public class LongConverter40Bit implements ByteArrayConverter {
}
@Override
- public Long fromBytes(final byte[] buffer) {
- return (((long) buffer[4] & 0xFFL) << 32)
- | (((long) buffer[3] & 0xFFL) << 24)
- | (((long) buffer[2] & 0xFFL) << 16)
- | (((long) buffer[1] & 0xFFL) << 8)
- | ((long) buffer[0] & 0xFFL);
+ public Long fromBytes(final byte[] buffer, int off) {
+ off += 5;
+ return (((long) buffer[--off] & 0xFFL) << 32)
+ | (((long) buffer[--off] & 0xFFL) << 24)
+ | (((long) buffer[--off] & 0xFFL) << 16)
+ | (((long) buffer[--off] & 0xFFL) << 8)
+ | ((long) buffer[--off] & 0xFFL);
}
@Override
- public void toBytes(final Long l, final byte[] buffer) {
- buffer[0] = (byte) ((l) & 0xFF);
- buffer[1] = (byte) ((l >> 8) & 0xFF);
- buffer[2] = (byte) ((l >> 16) & 0xFF);
- buffer[3] = (byte) ((l >> 24) & 0xFF);
- buffer[4] = (byte) ((l >> 32) & 0xFF);
+ public void toBytes(final Long l, final byte[] buffer, int off) {
+ --off;
+ buffer[++off] = (byte) ((l) & 0xFF);
+ buffer[++off] = (byte) ((l >> 8) & 0xFF);
+ buffer[++off] = (byte) ((l >> 16) & 0xFF);
+ buffer[++off] = (byte) ((l >> 24) & 0xFF);
+ buffer[++off] = (byte) ((l >> 32) & 0xFF);
}
}
diff --git a/src/main/java/com/moparisthebest/filelist/Main.java b/src/main/java/com/moparisthebest/filelist/Main.java
deleted file mode 100644
index 63f5e99..0000000
--- a/src/main/java/com/moparisthebest/filelist/Main.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.moparisthebest.filelist;
-
-import java.io.IOException;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Created by mopar on 2/9/17.
- */
-public class Main {
- public static void main(String[] args) throws IOException {
- System.out.println("str " + new Date());
- //final List list = new RandomAccessFileList<>("/home/mopar/raf2.list", new UnsignedLongConverter(5));
- final List list = new RandomAccessFileList<>("/home/mopar/raf2.list", LongConverter40Bit.instance); list.clear();
- /*
- System.out.println(list.get(0));
- System.out.println(((RandomAccessFileList)list).longSize());
- System.out.println(((RandomAccessFileList)list).get(((RandomAccessFileList)list).longSize() - 1));
- */
- //list.clear();
- /*
- long max = Integer.MAX_VALUE + 1000L;
- for(long l = 0; l < max; ++l)
- list.add(l);
- System.out.println("yay " + new Date());
- for(long l : list)
- System.out.println(l);
- */
- //if(true) return;
- System.out.println(Integer.MAX_VALUE);
- System.out.println(list);
- list.add(5L);
- System.out.println(list);
- System.out.println(list.get(0));
- list.add(99999999999L);
- System.out.println(list.get(1));
- list.add(6L);
- list.add(4L);
- System.out.println(list);
- list.sort(Long::compareTo);
- System.out.println(list);
- System.out.println("------");
- //if(true) return;
- for(long l = 0; l < 1000; ++l)
- //for(long l = 7; l < 11; ++l)
- list.add(l);
- System.out.println(list);
- list.sort(Long::compareTo);
- list.sort(Comparator.reverseOrder());
- System.out.println(list);
- }
-}
diff --git a/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java b/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java
index f308d5d..40fc845 100644
--- a/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java
+++ b/src/main/java/com/moparisthebest/filelist/RandomAccessFileList.java
@@ -9,13 +9,14 @@ import java.util.*;
/**
* Created by mopar on 2/9/17.
*/
-public class RandomAccessFileList extends AbstractList {
+public class RandomAccessFileList extends AbstractList implements AutoCloseable {
private final RandomAccessFile raf;
private final byte[] buffer;
private final ByteArrayConverter bac;
+ private final boolean close;
- public RandomAccessFileList(final RandomAccessFile raf, final ByteArrayConverter bac) {
+ private RandomAccessFileList(final RandomAccessFile raf, final boolean close, final ByteArrayConverter bac) {
Objects.requireNonNull(raf);
Objects.requireNonNull(bac);
if (bac.numBytes() < 1)
@@ -23,14 +24,25 @@ public class RandomAccessFileList extends AbstractList {
this.raf = raf;
this.buffer = new byte[bac.numBytes()];
this.bac = bac;
+ this.close = close;
+ }
+
+ public RandomAccessFileList(final RandomAccessFile raf, final ByteArrayConverter bac) {
+ this(raf, false, bac);
}
public RandomAccessFileList(final String name, final ByteArrayConverter bac) throws FileNotFoundException {
- this(new RandomAccessFile(name, "rw"), bac);
+ this(new RandomAccessFile(name, "rw"), true, bac);
}
public RandomAccessFileList(final File file, final ByteArrayConverter bac) throws FileNotFoundException {
- this(new RandomAccessFile(file, "rw"), bac);
+ this(new RandomAccessFile(file, "rw"), true, bac);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if(close)
+ raf.close();
}
public T get(final int index) {
@@ -45,7 +57,7 @@ public class RandomAccessFileList extends AbstractList {
raf.seek(index * buffer.length);
if (raf.read(buffer) != buffer.length)
throw new IOException("no full buffer to read, corrupted file?");
- return bac.fromBytes(buffer);
+ return bac.fromBytes(buffer, 0);
}
public int size() {
@@ -64,7 +76,7 @@ public class RandomAccessFileList extends AbstractList {
public boolean add(final T o) {
try {
raf.seek(raf.length());
- bac.toBytes(o, buffer);
+ bac.toBytes(o, buffer, 0);
raf.write(buffer);
return true;
} catch (IOException e) {
@@ -84,7 +96,7 @@ public class RandomAccessFileList extends AbstractList {
public T set(final long index, final T o) throws IOException {
final T ret = get(index);
raf.seek(index * buffer.length);
- bac.toBytes(o, buffer);
+ bac.toBytes(o, buffer, 0);
raf.write(buffer);
return ret;
}
@@ -98,6 +110,60 @@ public class RandomAccessFileList extends AbstractList {
}
}
+ public long indexedBinarySearch(final K key, final TransformComparator c) throws IOException {
+ long low = 0;
+ long high = this.longSize()-1;
+
+ while (low <= high) {
+ final long mid = (low + high) >>> 1;
+ final T midVal = this.get(mid);
+ final int cmp = c.compareTransform(key, midVal);
+
+ if (cmp > 0)
+ low = mid + 1;
+ else if (cmp < 0)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found
+ }
+
+ public long iteratorBinarySearch(final K key, final TransformComparator c) throws IOException {
+ long low = 0;
+ long high = this.longSize()-1;
+ ListIterator extends T> i = this.listIterator();
+
+ while (low <= high) {
+ final long mid = (low + high) >>> 1;
+ final T midVal = get(i, mid);
+ final int cmp = c.compareTransform(key, midVal);
+
+ if (cmp > 0)
+ low = mid + 1;
+ else if (cmp < 0)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found
+ }
+
+ private T get(final ListIterator extends T> i, final long index) {
+ T obj = null;
+ int pos = i.nextIndex();
+ if (pos <= index) {
+ do {
+ obj = i.next();
+ } while (pos++ < index);
+ } else {
+ do {
+ obj = i.previous();
+ } while (--pos > index);
+ }
+ return obj;
+ }
+
@Override
public void sort(final Comparator super T> c) {
try {
diff --git a/src/main/java/com/moparisthebest/filelist/SignedLongConverter.java b/src/main/java/com/moparisthebest/filelist/SignedLongConverter.java
index 86d26ab..b1e97ab 100644
--- a/src/main/java/com/moparisthebest/filelist/SignedLongConverter.java
+++ b/src/main/java/com/moparisthebest/filelist/SignedLongConverter.java
@@ -19,7 +19,7 @@ public class SignedLongConverter implements ByteArrayConverter {
}
@Override
- public Long fromBytes(final byte[] buffer) {
+ public Long fromBytes(final byte[] buffer, final int off) {
/*
if(true)
return (((long)buffer[0] << 56) +
@@ -31,7 +31,7 @@ public class SignedLongConverter implements ByteArrayConverter {
((buffer[6] & 255) << 8) +
((buffer[7] & 255) << 0));
*/
- int y = 0, x = (buffer.length * 8) - 8;
+ int y = off, x = (this.numBytes * 8) - 8;
if(debug) System.out.printf("l = (long)(buffer[%d] << %d);%n", y, x);
long l = (long)(buffer[y] << x);
x = x - 8;
@@ -40,7 +40,7 @@ public class SignedLongConverter implements ByteArrayConverter {
if(debug) System.out.printf("l += ((long)(buffer[%d] & 255) << %d);%n", y, x);
l += ((long)(buffer[y] & 255) << x);
}
- for (; y < buffer.length; x = x - 8, ++y) {
+ for (; y < this.numBytes; x = x - 8, ++y) {
if(debug) System.out.printf("l += (buffer[%d] & 255) << %d;%n", y, x);
l += (buffer[y] & 255) << x;
}
@@ -48,7 +48,7 @@ public class SignedLongConverter implements ByteArrayConverter {
}
@Override
- public void toBytes(final Long l, final byte[] buffer) {
+ public void toBytes(final Long l, final byte[] buffer, final int off) {
/*
writeBuffer[0] = (byte)(v >>> 56);
writeBuffer[1] = (byte)(v >>> 48);
@@ -59,21 +59,21 @@ public class SignedLongConverter implements ByteArrayConverter {
writeBuffer[6] = (byte)(v >>> 8);
writeBuffer[7] = (byte)(v >>> 0);
*/
- for(int y = 0, x = (buffer.length * 8) - 8; x > -1; x = x - 8, ++y) {
+ for(int y = off, x = (this.numBytes * 8) - 8; x > -1; x = x - 8, ++y) {
if(debug) System.out.printf("buffer[%d] = (byte) (l >>> %d);%n", y, x);
buffer[y] = (byte) (l >>> x);
}
}
public static void main(String[] args) {
- final ByteArrayConverter bac = new SignedLongConverter(5);
final byte[] buf = new byte[3]; // 5 99999999999L
+ final ByteArrayConverter bac = new SignedLongConverter(buf.length);
//System.out.println(4294967296L); System.out.println(Integer.MAX_VALUE * 2L); if(true)return;
//System.out.println(Long.MIN_VALUE + 500);
//bac.toBytes(99999999999L, buf); System.out.println(java.util.Arrays.toString(buf)); System.out.println(bac.fromBytes(buf)); if(true) return;
for(long l = 0, c = 0; ; ++l) {
- bac.toBytes(l, buf);
- c = bac.fromBytes(buf);
+ bac.toBytes(l, buf, 0);
+ c = bac.fromBytes(buf, 0);
if(l != c) {
System.out.printf("limit for %d bytes l = %d c = %d%n", buf.length, l, c);
return;
diff --git a/src/main/java/com/moparisthebest/filelist/TransformComparator.java b/src/main/java/com/moparisthebest/filelist/TransformComparator.java
new file mode 100644
index 0000000..184b345
--- /dev/null
+++ b/src/main/java/com/moparisthebest/filelist/TransformComparator.java
@@ -0,0 +1,11 @@
+package com.moparisthebest.filelist;
+
+/**
+ * Created by mopar on 2/10/17.
+ */
+@FunctionalInterface
+public interface TransformComparator {
+
+ int compareTransform(K o1, T o2);
+
+}
diff --git a/src/main/java/com/moparisthebest/filelist/UnsignedLongConverter.java b/src/main/java/com/moparisthebest/filelist/UnsignedLongConverter.java
index e55849e..5c24e50 100644
--- a/src/main/java/com/moparisthebest/filelist/UnsignedLongConverter.java
+++ b/src/main/java/com/moparisthebest/filelist/UnsignedLongConverter.java
@@ -17,17 +17,17 @@ public class UnsignedLongConverter implements ByteArrayConverter {
}
@Override
- public Long fromBytes(final byte[] buffer) {
+ public Long fromBytes(final byte[] buffer, final int off) {
long l = 0;
- for(int x = buffer.length - 1, y = (buffer.length * 8) - 8; x >= 0; --x, y = y - 8) {
+ for(int x = this.numBytes - 1, y = (this.numBytes * 8) - 8; x >= off; --x, y = y - 8) {
l |= (((long) buffer[x] & 0xFFL) << y);
}
return l;
}
@Override
- public void toBytes(final Long l, final byte[] buffer) {
- for(int x = 0, y = 0; x < buffer.length; ++x, y = y + 8) {
+ public void toBytes(final Long l, final byte[] buffer, final int off) {
+ for(int x = off, y = 0; x < this.numBytes; ++x, y = y + 8) {
buffer[x] = (byte) ((l >> y) & 0xFF);
}
}