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 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 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 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); } }