/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under The MIT license. */ package com.ttProject.unit.extra; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; /** * connect for bit data. * @author taktod */ public class BitConnector { /** logger */ @SuppressWarnings("unused") private Logger logger = Logger.getLogger(BitConnector.class); /** bit list for feeding */ private List<Bit> bits = null; /** flag for little endian */ private boolean littleEndianFlg = false; /** for data constructing */ private long data; private int left; private int size; private ByteBuffer buffer = null; /** * set the endian flag * @param flg true:little endian false:big endian */ public void setLittleEndianFlg(boolean flg) { littleEndianFlg = flg; } /** * is little endian working? * @return */ public boolean isLittleEndian() { return littleEndianFlg; } /** * connect * @param bits */ public ByteBuffer connect(Bit... bits) { data = 0; left = 0; size = 0; for(Bit bit : bits) { if(bit != null) { size += bit.getBitCount(); } } buffer = ByteBuffer.allocate((int)(Math.ceil(size / 8.0D))); for(Bit bit : bits) { if(bit == null) { continue; } if(bit instanceof ExpGolomb) { ExpGolomb eg = (ExpGolomb) bit; for(Bit egBit : eg.bits) { appendBit(egBit); } } else if(bit instanceof EbmlValue) { EbmlValue ebml = (EbmlValue)bit; appendBit(ebml.getEbmlNumBit()); Bit dataBit = ebml.getEbmlDataBit(); if(dataBit instanceof BitN) { BitN bitN = (BitN)dataBit; if(littleEndianFlg) { for(int i = bitN.bits.size() - 1;i >= 0;i --){ appendBit(bitN.bits.get(i)); } } else { for(Bit b : bitN.bits) { appendBit(b); } } } else { appendBit(dataBit); } } else if(bit instanceof BitN) { BitN bitN = (BitN)bit; if(littleEndianFlg) { for(int i = bitN.bits.size() - 1;i >= 0;i --){ appendBit(bitN.bits.get(i)); } } else { for(Bit b : bitN.bits) { appendBit(b); } } } else { appendBit(bit); } } if(buffer.position() != buffer.limit()) { if(littleEndianFlg) { writeBuffer(8 - left); } else { if(left != 0) { data <<= (8 - left); } writeBuffer(0); } } buffer.flip(); return buffer; } /** * append next bit */ private void appendBit(Bit b) { // if this bit is BitN, this must be trouble. if(littleEndianFlg) { data = data | (b.get() << left); left += b.bitCount; while(left >= 8) { left -= 8; writeBuffer(0); data >>>= 8; } } else { data = (data << b.bitCount) | b.get(); left += b.bitCount; while(left >= 8) { left -= 8; writeBuffer(left); } } } /** * put the data into buffer. * @param shift */ private void writeBuffer(int shift) { if(littleEndianFlg) { buffer.put((byte)(data & 0xFF)); } else { buffer.put((byte)((data >>> shift) & 0xFF)); } } /** * connect with the data of java.util.List * @param bits * @return */ public ByteBuffer connect(List<Bit> bits) { return connect(bits.toArray(new Bit[]{})); } /** * add feeding data * @param bits */ public void feed(List<Bit> bits) { if(this.bits == null) { this.bits = new ArrayList<Bit>(); } this.bits.addAll(bits); } /** * add feeding data * @param bits */ public void feed(Bit ... bits) { if(this.bits == null) { this.bits = new ArrayList<Bit>(); } for(Bit bit : bits) { this.bits.add(bit); } } /** * connect for feeding data. * @return */ public ByteBuffer connect() { if(bits == null) { return null; } return connect(bits); } }