package erjang; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.zip.Checksum; import erjang.driver.IO; import erjang.driver.IO.BARR; public abstract class EIOListVisitor { public void visit(ByteBuffer buf) { visit(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining()); } public void add(byte[] array) { visit(array, 0, array.length); } public void visit(byte[] array, int off, int len) { for (int i = 0; i < len; i++) { visit(array[off + i]); } } public void visitBits(int bits, int bitCount) { throw new IllegalArgumentException(); } abstract void visit(int aByte); public static long size( EObject io_list ) { final long[] size = new long[1]; io_list.visitIOList( new EIOListVisitor() { @Override public void visit(ByteBuffer buf) { size[0] += buf.remaining(); } @Override public void add(byte[] array) { size[0] += array.length; } @Override public void visit(byte[] array, int off, int len) { size[0] += len; } @Override void visit(int aByte) { size[0] += 1; } }); return size[0]; } public static ByteBuffer[] collectv( EObject io_list ) { final List<ByteBuffer> list = new ArrayList<ByteBuffer>(); final IO.BARR[] barr = new IO.BARR[1]; io_list.visitIOList( new EIOListVisitor() { private void flush() { if (barr[0] != null) { list.add(barr[0].wrap()); barr[0] = null; } } @Override public void visit(ByteBuffer buf) { flush(); list.add(buf); } @Override public void visit(byte[] array, int off, int len) { if (barr[0] != null && len < 32) { barr[0].write(array, off, len); } else { flush(); list.add(ByteBuffer.wrap(array, off, len)); } } @Override void visit(int aByte) { if (barr[0] == null) { barr[0] = new BARR(); } barr[0].write(aByte); } }); if (barr[0] != null) { list.add(barr[0].wrap()); barr[0] = null; } return list.toArray(new ByteBuffer[ list.size() ]); } public static ByteBuffer collect( EObject io_list ) { EBinary bin; if ((bin = io_list.testBinary()) != null) { return bin.toByteBuffer(); } @SuppressWarnings("resource") final BARR out = new BARR(); io_list.visitIOList( new EIOListVisitor() { @Override public void visit(byte[] array, int off, int len) { out.write(array, off, len); } @Override void visit(int aByte) { out.write(aByte); } }); return out.wrap(); } public static EBitString collect_bitstring( EObject io_list ) { EBitString bin; if ((bin = io_list.testBitString()) != null) { return bin; } final int[] extra_bits = new int[1]; @SuppressWarnings("resource") final BARR out = new BARR(); io_list.visitIOList( new EIOListVisitor() { @Override public void visit(byte[] array, int off, int len) { if (extra_bits[0] != 0) throw ERT.badarg(); out.write(array, off, len); } @Override void visit(int aByte) { if (extra_bits[0] != 0) throw ERT.badarg(); out.write(aByte); } @Override public void visitBits(int bits, int bitCount) { out.write( bits << (8-bitCount) ); extra_bits[0] = bitCount; } }); ByteBuffer bb = out.wrap(); if (extra_bits[0] == 0) { return new EBinary(bb.array(), 0, bb.limit()); } else { return EBitString.make(bb.array(), 0, bb.limit()-1, extra_bits[0]); } } public static void update( EObject io_list, final Checksum checksum ) { io_list.visitIOList( new EIOListVisitor() { @Override public void visit(byte[] array, int off, int len) { checksum.update(array, off, len); } @Override void visit(int aByte) { checksum.update(aByte); } }); } }