Skip to content

Instantly share code, notes, and snippets.

@dobesv
Created March 8, 2012 02:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dobesv/1998118 to your computer and use it in GitHub Desktop.
Save dobesv/1998118 to your computer and use it in GitHub Desktop.
Add Buf subclass supporting any kind of java.nio.ByteBuffer (not just MmapByteBuffer)
package fan.sys;
import java.nio.MappedByteBuffer;
public class MmapBuf extends NioBuf {
MmapBuf(File file, MappedByteBuffer mmap) {
super(mmap);
this.file = file;
this.mmap = mmap;
}
public Buf flush() {
mmap.force();
return this;
}
public Type typeof() {
return Sys.MmapBufType;
}
private File file;
private MappedByteBuffer mmap;
}
package fan.sys;
import java.io.*;
import java.nio.*;
import fan.sys.Buf;
public class NioBuf extends Buf {
// ////////////////////////////////////////////////////////////////////////
// Constructor
// ////////////////////////////////////////////////////////////////////////
public NioBuf(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
this.out = new NioBufOutStream();
this.in = new NioBufInStream();
}
// ////////////////////////////////////////////////////////////////////////
// Obj
// ////////////////////////////////////////////////////////////////////////
public Type typeof() {
return Sys.MemBufType; // TODO This is the wrong type here
}
// ////////////////////////////////////////////////////////////////////////
// Buf Support
// ////////////////////////////////////////////////////////////////////////
public final long size() {
return byteBuffer.limit();
}
public final void size(long x) {
byteBuffer.limit((int) x);
}
public final long pos() {
return byteBuffer.position();
}
final void pos(long x) {
byteBuffer.position((int) x);
}
public final int getByte(long pos) {
return byteBuffer.get((int) pos) & 0xff;
}
public final void setByte(long pos, int x) {
byteBuffer.put((int) pos, (byte) x);
}
public final void getBytes(long pos, byte[] dst, int off, int len) {
int oldPos = byteBuffer.position();
byteBuffer.position((int) pos);
byteBuffer.get(dst, off, len);
byteBuffer.position(oldPos);
}
public final void pipeTo(byte[] dst, int dstPos, int len) {
byteBuffer.get(dst, dstPos, len);
}
public final void pipeTo(OutputStream dst, long lenLong) throws IOException {
byte[] temp = temp();
int len = (int) lenLong;
int total = 0;
while (total < len) {
int n = Math.min(temp.length, len - total);
byteBuffer.get(temp, 0, n);
dst.write(temp, 0, n);
total += n;
}
}
public final void pipeTo(RandomAccessFile dst, long lenLong)
throws IOException {
byte[] temp = temp();
int len = (int) lenLong;
int total = 0;
while (total < len) {
int n = Math.min(temp.length, len - total);
byteBuffer.get(temp, 0, n);
dst.write(temp, 0, n);
total += n;
}
}
public final void pipeTo(ByteBuffer dst, int len) {
pipe(byteBuffer, dst, len);
}
void pipe(ByteBuffer src, ByteBuffer dst, int len) {
// NIO has one lame method for bulk transfer
// and it doesn't let us pass in a length
byte[] temp = temp();
int total = 0;
while (total < len) {
int n = Math.min(temp.length, len - total);
src.get(temp, 0, n);
dst.put(temp, 0, n);
total += n;
}
}
public final void pipeFrom(byte[] src, int srcPos, int len) {
byteBuffer.put(src, srcPos, len);
}
public final long pipeFrom(InputStream src, long lenLong)
throws IOException {
byte[] temp = temp();
int len = (int) lenLong;
int total = 0;
while (total < len) {
int n = src.read(temp, 0, Math.min(temp.length, len - total));
if (n < 0)
return total == 0 ? -1 : total;
byteBuffer.put(temp, 0, n);
total += n;
}
return total;
}
public final long pipeFrom(RandomAccessFile src, long lenLong)
throws IOException {
byte[] temp = temp();
int len = (int) lenLong;
int total = 0;
while (total < len) {
int n = src.read(temp, 0, Math.min(temp.length, len - total));
if (n < 0)
return total == 0 ? -1 : total;
byteBuffer.put(temp, 0, n);
total += n;
}
return total;
}
public final int pipeFrom(ByteBuffer src, int len) {
pipe(src, byteBuffer, len);
return len;
}
// ////////////////////////////////////////////////////////////////////////
// Buf API
// ////////////////////////////////////////////////////////////////////////
public long capacity() {
return size();
}
public void capacity(long x) {
throw UnsupportedErr.make("capacity fixed");
}
// For the mmap subclass this would call force()
public Buf flush() {
return this;
}
public final boolean close() {
return true;
}
public final String toHex() {
throw UnsupportedErr.make();
}
public Buf toDigest(String algorithm) {
throw UnsupportedErr.make();
}
// ////////////////////////////////////////////////////////////////////////
// Utils
// ////////////////////////////////////////////////////////////////////////
final byte[] temp() {
if (temp == null)
temp = new byte[1024];
return temp;
}
// ////////////////////////////////////////////////////////////////////////
// MmapBufOutStream
// ////////////////////////////////////////////////////////////////////////
class NioBufOutStream extends OutStream {
public final OutStream write(long v) {
return w((int) v);
}
public final OutStream w(int v) {
byteBuffer.put((byte) v);
return this;
}
public OutStream writeBuf(Buf other, long n) {
other.pipeTo(byteBuffer, (int) n);
return this;
}
public OutStream writeChar(long c) {
charsetEncoder.encode((char) c, this);
return this;
}
public OutStream writeChar(char c) {
charsetEncoder.encode(c, this);
return this;
}
public OutStream flush() {
NioBuf.this.flush();
return this;
}
}
// ////////////////////////////////////////////////////////////////////////
// NioBufInStream
// ////////////////////////////////////////////////////////////////////////
class NioBufInStream extends InStream {
public Long read() {
int n = r();
return n < 0 ? null : FanInt.pos[n];
}
public int r() {
if (byteBuffer.remaining() <= 0)
return -1;
return byteBuffer.get() & 0xff;
}
public Long readBuf(Buf other, long n) {
int left = byteBuffer.remaining();
if (left <= 0)
return null;
if (left < n)
n = left;
int read = other.pipeFrom(byteBuffer, (int) n);
if (read < 0)
return null;
return Long.valueOf(read);
}
public InStream unread(long n) {
return unread((int) n);
}
public InStream unread(int n) {
byteBuffer.put(byteBuffer.position() - 1, (byte) n);
return this;
}
public Long peek() {
return FanInt.pos[byteBuffer.get(byteBuffer.position())];
}
}
// ////////////////////////////////////////////////////////////////////////
// Fields
// ////////////////////////////////////////////////////////////////////////
public ByteBuffer byteBuffer;
private byte[] temp;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment