Mercurial > hg > Members > sugi > MessagePack-java
view src/main/java/org/msgpack/io/LinkedBufferInput.java @ 0:cb825acd883a
first commit
author | sugi |
---|---|
date | Sat, 18 Oct 2014 15:06:15 +0900 |
parents | |
children |
line wrap: on
line source
// // MessagePack for Java // // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.msgpack.io; import java.io.IOException; import java.io.EOFException; import java.util.LinkedList; import java.util.Iterator; import java.util.NoSuchElementException; import java.nio.ByteBuffer; public class LinkedBufferInput extends AbstractInput { LinkedList<ByteBuffer> link; int writable; private int nextAdvance; private byte[] tmpBuffer; private ByteBuffer tmpByteBuffer; private final int bufferSize; public LinkedBufferInput(int bufferSize) { this.link = new LinkedList<ByteBuffer>(); this.writable = -1; this.tmpBuffer = new byte[8]; this.tmpByteBuffer = ByteBuffer.wrap(tmpBuffer); this.bufferSize = bufferSize; } public int read(byte[] b, int off, int len) throws EOFException { if (link.isEmpty()) { return 0; } int olen = len; while (true) { ByteBuffer bb = link.getFirst(); if (len < bb.remaining()) { bb.get(b, off, len); incrReadByteCount(len); return olen; } int rem = bb.remaining(); bb.get(b, off, rem); incrReadByteCount(rem); len -= rem; off += rem; if (!removeFirstLink(bb)) { break; } } return olen - len; } public boolean tryRefer(BufferReferer ref, int len) throws IOException { ByteBuffer bb = null; try { bb = link.getFirst(); } catch(NoSuchElementException e) {} if (bb == null) { throw new EndOfBufferException(); } else if (bb.remaining() < len) { return false; } boolean success = false; int pos = bb.position(); int lim = bb.limit(); try { bb.limit(pos + len); ref.refer(bb, true); incrReadByteCount(len); success = true; } finally { bb.limit(lim); if (success) { bb.position(pos + len); } else { bb.position(pos); } if (bb.remaining() == 0) { removeFirstLink(bb); } } return true; } public byte readByte() throws EOFException { ByteBuffer bb = null; try { bb = link.getFirst(); } catch(NoSuchElementException e) {} if (bb == null || bb.remaining() == 0) { throw new EndOfBufferException(); } byte result = bb.get(); incrReadOneByteCount(); if (bb.remaining() == 0) { removeFirstLink(bb); } return result; } public void advance() { if (link.isEmpty()) { return; } int len = nextAdvance; ByteBuffer bb; while (true) { bb = link.getFirst(); if (len < bb.remaining()) { bb.position(bb.position() + len); break; } len -= bb.remaining(); bb.position(bb.position() + bb.remaining()); if (!removeFirstLink(bb)) { break; } } incrReadByteCount(nextAdvance); nextAdvance = 0; } private boolean removeFirstLink(ByteBuffer first) { if (link.size() == 1) { if (writable >= 0) { first.position(0); first.limit(0); writable = first.capacity(); return false; } else { link.removeFirst(); return false; } } else { link.removeFirst(); return true; } } private void requireMore(int n) throws EOFException { int off = 0; for (ByteBuffer bb : link) { if (n <= bb.remaining()) { int pos = bb.position(); bb.get(tmpBuffer, off, n); bb.position(pos); return; } int rem = bb.remaining(); int pos = bb.position(); bb.get(tmpBuffer, off, rem); bb.position(pos); n -= rem; off += rem; } throw new EndOfBufferException(); } private ByteBuffer require(int n) throws EOFException { ByteBuffer bb = null; try { bb = link.getFirst(); } catch(NoSuchElementException e) {} if (bb == null) { throw new EndOfBufferException(); } if (n <= bb.remaining()) { nextAdvance = n; return bb; } else { requireMore(n); nextAdvance = n; return tmpByteBuffer; } } public byte getByte() throws EOFException { ByteBuffer bb = require(1); return bb.get(bb.position()); } public short getShort() throws EOFException { ByteBuffer bb = require(2); return bb.getShort(bb.position()); } public int getInt() throws EOFException { ByteBuffer bb = require(4); return bb.getInt(bb.position()); } public long getLong() throws EOFException { ByteBuffer bb = require(8); return bb.getLong(bb.position()); } public float getFloat() throws EOFException { ByteBuffer bb = require(4); return bb.getFloat(bb.position()); } public double getDouble() throws EOFException { ByteBuffer bb = require(8); return bb.getDouble(bb.position()); } public void feed(byte[] b) { feed(b, 0, b.length, false); } public void feed(byte[] b, boolean reference) { feed(b, 0, b.length, reference); } public void feed(byte[] b, int off, int len) { feed(b, off, len, false); } public void feed(byte[] b, int off, int len, boolean reference) { if (reference) { if (writable > 0 && link.getLast().remaining() == 0) { link.add(link.size()-1, ByteBuffer.wrap(b, off, len)); return; } link.addLast(ByteBuffer.wrap(b, off, len)); writable = -1; return; } ByteBuffer bb = null; try { bb = link.getLast(); } catch(NoSuchElementException e) {} if (len <= writable) { int pos = bb.position(); bb.position(bb.limit()); bb.limit(bb.limit() + len); bb.put(b, off, len); bb.position(pos); writable = bb.capacity() - bb.limit(); return; } if (writable > 0) { int pos = bb.position(); bb.position(bb.limit()); bb.limit(bb.limit() + writable); bb.put(b, off, writable); bb.position(pos); off += writable; len -= writable; writable = 0; } int sz = Math.max(len, bufferSize); ByteBuffer nb = ByteBuffer.allocate(sz); nb.put(b, off, len); nb.limit(len); nb.position(0); link.addLast(nb); writable = sz - len; } public void feed(ByteBuffer b) { feed(b, false); } public void feed(ByteBuffer buf, boolean reference) { if (reference) { if (writable > 0 && link.getLast().remaining() == 0) { link.add(link.size()-1, buf); return; } link.addLast(buf); writable = -1; return; } int rem = buf.remaining(); ByteBuffer bb = null; try { bb = link.getLast(); } catch(NoSuchElementException e) {} if (rem <= writable) { int pos = bb.position(); bb.position(bb.limit()); bb.limit(bb.limit() + rem); bb.put(buf); bb.position(pos); writable = bb.capacity() - bb.limit(); return; } if (writable > 0) { int pos = bb.position(); bb.position(bb.limit()); bb.limit(bb.limit() + writable); buf.limit(writable); bb.put(buf); bb.position(pos); rem -= writable; buf.limit(buf.limit() + rem); writable = 0; } int sz = Math.max(rem, bufferSize); ByteBuffer nb = ByteBuffer.allocate(sz); nb.put(buf); nb.limit(rem); nb.position(0); link.addLast(nb); writable = sz - rem; } public void clear() { if (writable >= 0) { ByteBuffer bb = link.getLast(); link.clear(); bb.position(0); bb.limit(0); link.addLast(bb); writable = bb.capacity(); } else { link.clear(); writable = -1; } } public void copyReferencedBuffer() { if (link.isEmpty()) { return; } int size = 0; for(ByteBuffer bb : link) { size += bb.remaining(); } if (size == 0) { return; } if (writable >= 0) { ByteBuffer last = link.removeLast(); byte[] copy = new byte[size - last.remaining()]; int off = 0; for(ByteBuffer bb : link) { int len = bb.remaining(); bb.get(copy, off, len); off += len; } link.clear(); link.add(ByteBuffer.wrap(copy)); link.add(last); } else { byte[] copy = new byte[size]; int off = 0; for(ByteBuffer bb : link) { int len = bb.remaining(); bb.get(copy, off, len); off += len; } link.clear(); link.add(ByteBuffer.wrap(copy)); writable = 0; } } public int getSize() { int size = 0; for(ByteBuffer bb : link) { size += bb.remaining(); } return size; } public void close() { } }