/*
* Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/
* All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package javaFlacEncoder;
/**
* EncodedElement class provides is used to store data in the proper bitstream
* format for FLAC audio. Methods are provided to easily append values to the
* bitstream. Conceptually, an EncodedElement is a list structure, in which the
* encoded data is stored in a byte array. It is assumed that any data stored by
* objects of this class will be retrieved through direct access to the
* underlying byte array. This byte array is exposed to outside objects
* primarily to allow faster access than "proper" object-oriented design might
* allow.
*
* @author Preston Lacey
*/
public class EncodedElement {
/** For Debugging: Higher level equals more debug statements */
static int DEBUG_LEV = 0;
/** Previous element in list. At current times, this should not be dependend
* on to be set */
EncodedElement previous = null;
/** Next element in list. */
EncodedElement next = null;
/** Data stored by this element. Member usableBits should be used to track
* the last valid index at a bit level. */
byte[] data = null;
/** Use to track the last valid index of the data array at a bit level. For
* example, a value of "10" would mean the first byte and two low-order bits
* of the second byte are used. usableBits must always be equal or greater
* than offset.
*/
int usableBits = 0;//i.e, the last write location in 'data' array.
/** Used to signify the index of the first valid bit of the data array. For
* purposes of speed, it is not always best to pack the data starting at
* bit zero of first byte. offset must always be less than or equal to
* usableBits.
*/
protected int offset;
/**
* Constructor, creates an empty element with offset of zero and array size
* of 100. This array can be replaced with a call to setData(...).
*/
public EncodedElement() {
offset = 0;
usableBits = 0;
data = new byte[100];
}
/**
* Constructor. Creates an EncodedElement with the given size and offset
* @param size Size of data array to use(in bytes)
* @param off Offset to use for this element. Usablebits will also be set
* to this value.
*/
public EncodedElement(int size, int off) {
data = new byte[size];
usableBits = off;
offset = off;
}
/**
* Completely clear this element and use the given size and offset for the
* new data array.
*
* @param size Size of data array to use(in bytes)
* @param off Offset to use for this element. Usablebits will also be set to
* this value.
*/
public void clear(int size, int off) {
next = null;
previous = null;
data = new byte[size];
offset = off;
usableBits = off;
}
/**
* Set the object previous to this in the list.
* @param ele the object to set as previous.
* @return <code>void</code>
*
* Precondition: none
* Post-condition: getPrevious() will now return the given object. Any
* existing “previous” was lost.
*/
void setPrevious(EncodedElement ele) {
previous = ele;
}
/**
* Set the object next to this in the list.
* @param ele the object to set as next.
* @return void
* Pre-condition: none
* Post-condition: getNext() will now return the given object. Any existing
* “next” was lost.
*/
void setNext(EncodedElement ele) {
next = ele;
}
/**
* Get the object stored as the previous item in this list.
*
* @return EncodedElement
*/
EncodedElement getPrevious() {
return previous;
}
/**
* Get the object stored as the next item in this list.
*
* @param EncodedElement;
*/
EncodedElement getNext() {
return next;
}
/**
* Set the byte array stored by this object.
*
* @param data the byte array to store.
*
* Pre-condition: None
* Post-condition: 'data' is now stored by this object. Any previous data
* stored was lost.
*/
void setData(byte[] data) {
this.data = data;
}
/**
* Set the number of bits of the given array that are usable data. Data is
* packed from the lower indices to higher.
*
* @param bits the value to store
*/
void setUsableBits(int bits) {
usableBits = bits;
}
/**
* Get the byte array stored by this object(null if not set).
*
* @param byte[] the data stored in this byte[] is likely not all usable.
* Method getUsableBits() should be used to determine such.
*/
byte[] getData() {
return data;
}
/**
* get the number of bits usable in the stored array.
* @return int
*/
int getUsableBits() {
return usableBits;
}
/**
* Return the last element of the list given. This is a static funtion to
* provide minor speed improvement. Loops through all elements' "next"
* pointers, till the last is found.
* @param e EncodedElement list to find end of.
* @return Final element in list.
*/
protected static EncodedElement getEnd_S(EncodedElement e) {
if(e == null)
return null;
EncodedElement temp = e.next;
EncodedElement end = e;
while(temp != null) {
end = temp;
temp = temp.next;
}
return end;
}
/**
* Return the last element of the list given. Loops through all elements'
* "next" pointers, till the last is found.
* @return last element in this list
*/
public EncodedElement getEnd() {
EncodedElement temp = next;
EncodedElement end = this;
while(temp != null) {
end = temp;
temp = temp.next;
}
return end;
}
/**
* Attach an element to the end of this list.
*
* @param e Element to attach.
* @return True if element was attached, false otherwise.
*/
public boolean attachEnd(EncodedElement e) {
if(DEBUG_LEV > 0)
System.err.println("EncodedElement::attachEnd : Begin");
boolean attached = true;
EncodedElement current = this;
while(current.getNext() != null) {
current = current.getNext();
}
current.setNext(e);
e.setPrevious(current);
if(DEBUG_LEV > 0)
System.err.println("EncodedElement::attachEnd : End");
return attached;
}
/**
* Add a number of bits from a long to the end of this list's data. Will
* add a new element if necessary. The bits stored are taken from the lower-
* order of input.
*
* @param input Long containing bits to append to end.
* @param bitCount Number of bits to append.
* @return EncodedElement which actually contains the appended value.
*/
public EncodedElement addLong(long input, int bitCount) {
if(next != null) {
EncodedElement end = EncodedElement.getEnd_S(next);
return end.addLong(input, bitCount);
}
else if(data.length*8 <= usableBits+bitCount) {
//create child and attach to next.
//Set child's offset appropriately(i.e, manually set usable bits)
int tOff = usableBits %8;
int size = data.length/2+1;
//guarantee that our new element can store our given value
if(size < bitCount) size = bitCount*10;
next = new EncodedElement(size, tOff);
//add int to child
return next.addLong(input, bitCount);
}
//At this point, we have the space, and we are the end of the chain.
int startPos = this.usableBits;
byte[] dest = this.data;
EncodedElement.addLong(input, bitCount, startPos, dest);
usableBits += bitCount;
return this;
}
/**
* Add a number of bits from an int to the end of this list's data. Will
* add a new element if necessary. The bits stored are taken from the lower-
* order of input.
*
* @param input Int containing bits to append to end.
* @param bitCount Number of bits to append.
* @return EncodedElement which actually contains the appended value.
*/
public EncodedElement addInt(int input, int bitCount) {
if(next != null) {
EncodedElement end = EncodedElement.getEnd_S(next);
return end.addInt(input, bitCount);
}
else if(data.length*8 < usableBits+bitCount) {
//create child and attach to next.
//Set child's offset appropriately(i.e, manually set usable bits)
int tOff = usableBits %8;
//int size = data.length/2+1;
int size = 1000;
//guarantee that our new element can store our given value
//if(size <= bitCount+tOff) size = (size+tOff+bitCount)*10;
next = new EncodedElement(size, tOff);
System.err.println("creating next node of size:bitCount "+size+
":"+bitCount+":"+usableBits+":"+data.length);
System.err.println("value: "+input);
//+this.toString()+"::"+next.toString());
//add int to child
return next.addInt(input, bitCount);
}
else {
//At this point, we have the space, and we are the end of the chain.
int startPos = this.usableBits;
byte[] dest = this.data;
EncodedElement.addInt(input, bitCount, startPos, dest);
usableBits += bitCount;
return this;
}
}
/**
* Append an equal number of bits from each int in an array within given
* limits to the end of this list.
*
* @param inputArray Array storing input values.
* @param bitSize number of bits to store from each value.
* @param start index of first usable index.
* @param skip number of indices to skip between values(in case input data
* is interleaved with non-desirable data).
* @param countA Number of total indices to store from.
* @return EncodedElement containing end of packed data. Data may flow
* between multiple EncodedElement's, if an existing element was not large
* enough for all values.
*/
public EncodedElement packInt(int[] inputArray, int bitSize,
int start, int skip, int countA) {
//go to end if we're not there.
if(next != null) {
EncodedElement end = EncodedElement.getEnd_S(next);
return end.packInt(inputArray, bitSize, start, skip, countA);
}
//calculate how many we can pack into current.
int writeCount = (data.length*8 - usableBits) / bitSize;
if(writeCount > countA) writeCount = countA;
//pack them and update usable bits.
EncodedElement.packInt(inputArray, bitSize, usableBits, start, skip, countA, data);
usableBits += writeCount * bitSize;
//if more remain, create child object and add there
countA -= writeCount;
if(countA > 0) {
int tOff = usableBits %8;
int size = data.length/2+1;
//guarantee that our new element can store our given value
if(size < bitSize*countA) size = bitSize*countA+10;
next = new EncodedElement(size, tOff);
//add int to child
return next.packInt(inputArray, bitSize, start+writeCount*(skip+1), skip, countA);
}
else {
//return last object we write to.
return this;
}
}
/**
* Pack a number of bits from each int of an array(within given limits)to
* the end of this list.
*
* @param inputA Array containing input values.
* @param inputBits Array containing number of bits to use for each index
* packed. This array should be equal in size to the inputA array.
* @param inputOffset Index of first usable index.
* @param countA Number of indices to pack.
* @return EncodedElement containing end of packed data. Data may flow
* between multiple EncodedElement's, if an existing element was not large
* enough for all values.
*/
public EncodedElement packIntByBits(int[] inputA, int[] inputBits, int inputOffset,
int countA) {
//go to end if we're not there.
if(next != null) {
EncodedElement end = EncodedElement.getEnd_S(next);
return end.packIntByBits(inputA, inputBits, inputOffset, countA);
}
//calculate how many we can pack into current.
int writeBitsRemaining = data.length*8 - usableBits;
int willWrite = 0;
int writeCount = 0;
//System.err.println("writeBitsRemaining: " + writeBitsRemaining);
for(int i = 0; i < countA; i++) {
writeBitsRemaining -= inputBits[inputOffset+i];
if(writeBitsRemaining >= 0) {
writeCount++;
willWrite += inputBits[inputOffset+i];
}
else
break;
}
//pack them and update usable bits.
if(writeCount > 0) {
EncodedElement.packIntByBits(inputA, inputBits, inputOffset,
writeCount, usableBits, data);
usableBits += willWrite;
}
//if more remain, create child object and add there
countA -= writeCount;
if(countA > 0) {
inputOffset += writeCount;
int tOff = usableBits %8;
int size = data.length/2+1;
//guarantee that our new element can store our given value
int remainingToWrite = 0;
for(int i = 0; i < countA; i++) {
remainingToWrite += inputBits[inputOffset+i];
}
remainingToWrite = remainingToWrite / 8 + 1;
if(size < remainingToWrite) size = remainingToWrite+10;
//System.err.println("remaining: "+remainingToWrite);
//System.err.println("creating size/offset : "+size+":"+tOff);
next = new EncodedElement(size, tOff);
//add int to child
return next.packIntByBits(inputA, inputBits, inputOffset, countA);
}
else {
//System.err.println("returning....done");
//return if this is last object we wrote to.
return this;
}
}
/**
* Total number of usable bits stored by this entire list. This sums the
* difference of each list element's "usableBits" and "offset".
* @return Total valid bits in this list.
*/
public int getTotalBits() {
//this total calculates and removes the bits reserved for "offset"
// between the different children.
int total = 0;
EncodedElement iter = this;
while(iter != null) {
total += iter.usableBits - iter.offset;
iter = iter.next;
}
return total;
}
/**
* This method adds a given number of bits of an int to a byte array.
* @param value int to store bits from
* @param count number of low-order bits to store
* @param startPos start bit location in array to begin writing
* @param dest array to store bits in. dest MUST have enough space to store
* the given data, or this function will fail.
*/
public static void addInt(int value, int count, int startPos, byte[] dest) {
int currentByte = startPos/8;
int currentOffset = startPos%8;
//int upShift = 32-count;
//upShift += (8-currentOffset);
//int upShift = 39-count+currentOffset;
int upShift = 40-count-currentOffset;
//get the value to a workable place and clear the extraneous bits
long upperMask = -1 >>> (63-count);
long val = (long)value & upperMask;
val = val << upShift;
//get the bytes ready
int []bs = new int[5];
bs[4] = (byte)val;
val = val >> 8;
bs[3] = (byte)val;
val = val >> 8;
bs[2] = (byte)val;
val = val >> 8;
bs[1] = (byte)val;
val = val >> 8;
bs[0] = (byte)val;
//byte One
int bIndex = 0;
if(currentOffset > 0) {
int b1Mask = 255 >> currentOffset;
int bitRoom = 8-currentOffset;
int lowerRoom = bitRoom - count;
if(lowerRoom > 0) {
b1Mask = b1Mask >>> lowerRoom;
b1Mask = b1Mask << lowerRoom;
}
bs[0] = bs[0] & b1Mask;
int b1d = dest[currentByte] & ~b1Mask;
dest[currentByte++] = (byte)(bs[0] | b1d);
count -= bitRoom;
bIndex++;
}
//int bIndex = 1;
int midCount = count/8;
switch(midCount) {
case 4: dest[currentByte++] = (byte)bs[bIndex++];
case 3: dest[currentByte++] = (byte)bs[bIndex++];
case 2: dest[currentByte++] = (byte)bs[bIndex++];
case 1: dest[currentByte++] = (byte)bs[bIndex++];break;
}
count -= midCount*8;
if(count > 0) {
//int lastMask = 255 >> 8-count;
int lastMask = 255 << 8-count;
dest[currentByte] = (byte)(dest[currentByte] & ~lastMask);
dest[currentByte] = (byte)(bs[bIndex] | dest[currentByte]);
}
}
/** public static void addIntOld(int input, int count, int startPos, byte[] dest) {
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::addInt : Begin");
int currentByte = startPos/8;
int currentOffset = startPos%8;
int bitRoom;//how many bits can be placed in current byte
int upMask;//to clear upper bits(lower bits auto-cleared by L-shift
int downShift;//bits to shift down, isolating top bits of input
int upShift;//bits to shift up, packing byte from top.
while(count > 0) {
//find how many bits can be placed in current byte
bitRoom = 8-currentOffset;
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
downShift = count-bitRoom;
upMask = 255 >>> currentOffset;
upShift = 0;
if(downShift < 0) {
//upMask = 255 >>> bitRoom-count;
upShift = bitRoom - count;
upMask = 255 >>> (currentOffset+upShift);
downShift = 0;
}
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
int currentBits = (input >>> downShift) & (upMask);
//shift bits back up to match offset
currentBits = currentBits << upShift;
upMask = (byte)upMask << upShift;
dest[currentByte] = (byte)(dest[currentByte] & (~upMask));
//merge bytes~
dest[currentByte] = (byte)(dest[currentByte] | currentBits);
//System.out.println("new currentByte: " + dest[currentByte]);
count -= bitRoom;
currentOffset = 0;
currentByte++;
}
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::addInt : End");
}
**/
/**
* This method adds a given number of bits of a long to a byte array.
* @param input long to store bits from
* @param count number of low-order bits to store
* @param startPos start bit location in array to begin writing
* @param dest array to store bits in. dest MUST have enough space to store
* the given data, or this function will fail.
*/
public static void addLong(long input, int count, int startPos, byte[] dest) {
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::addLong : Begin");
int currentByte = startPos/8;
int currentOffset = startPos%8;
int bitRoom;//how many bits can be placed in current byte
long upMask;//to clear upper bits(lower bits auto-cleared by L-shift
int downShift;//bits to shift down, isolating top bits of input
int upShift;//bits to shift up, packing byte from top.
while(count > 0) {
//find how many bits can be placed in current byte
bitRoom = 8-currentOffset;
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
downShift = count-bitRoom;
upMask = 255 >>> currentOffset;
upShift = 0;
if(downShift < 0) {
//upMask = 255 >>> bitRoom-count;
upShift = bitRoom - count;
upMask = 255 >>> (currentOffset+upShift);
downShift = 0;
}
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
long currentBits = (input >>> downShift) & (upMask);
//shift bits back up to match offset
currentBits = currentBits << upShift;
upMask = (byte)upMask << upShift;
dest[currentByte] = (byte)(dest[currentByte] & (~upMask));
//merge bytes~
dest[currentByte] = (byte)(dest[currentByte] | currentBits);
//System.out.println("new currentByte: " + dest[currentByte]);
count -= bitRoom;
currentOffset = 0;
currentByte++;
}
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::addLong : End");
}
/** public static void packIntOLD_WORKING(int[] inputArray, int startBitSize, int startPos,
int start, int skip, int count, byte[] dest) {
if(DEBUG_LEV > 0)
System.err.println("EncodedElement::packInt : Begin");
if(DEBUG_LEV > 10)
System.err.println("start:skip:count : " +start+":"+skip+":"+count);
for(int i = 0; i < count; i++) {
addInt(inputArray[i*(skip+1)+start], startBitSize, startPos, dest);
startPos+=startBitSize;
}
}
**/
/**
* Append an equal number of bits from each int in an array within given
* limits to the given byte array.
*
* @param inputArray Array storing input values.
* @param bitSize number of bits to store from each value.
* @param start index of first usable index.
* @param skip number of indices to skip between values(in case input data
* is interleaved with non-desirable data).
* @param countA Number of total indices to store from.
* @param startPosIn First usable index in destination array(byte
* index = startPosIn/8, bit within that byte = startPosIn%8)
* @param dest Destination array to store input values in. This array *must*
* be large enough to store all values or this method will fail in an
* undefined manner.
*/
public static void packInt(int[] inputArray, int bitSize, int startPosIn,
int start, int skip, int countA, byte[] dest) {
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::packInt : Begin");
for(int valI = 0; valI < countA; valI++) {
//int input = inputArray[valI];
int input = inputArray[valI*(skip+1)+start];
int count = bitSize;
int startPos = startPosIn+valI*bitSize;
int currentByte = startPos/8;
int currentOffset = startPos%8;
int bitRoom;//how many bits can be placed in current byte
int upMask;//to clear upper bits(lower bits auto-cleared by L-shift
int downShift;//bits to shift down, isolating top bits of input
int upShift;//bits to shift up, packing byte from top.
while(count > 0) {
//find how many bits can be placed in current byte
bitRoom = 8-currentOffset;
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
downShift = count-bitRoom;
upMask = 255 >>> currentOffset;
upShift = 0;
if(downShift < 0) {
//upMask = 255 >>> bitRoom-count;
upShift = bitRoom - count;
upMask = 255 >>> (currentOffset+upShift);
downShift = 0;
}
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
int currentBits = (input >>> downShift) & (upMask);
//shift bits back up to match offset
currentBits = currentBits << upShift;
upMask = (byte)upMask << upShift;
dest[currentByte] = (byte)(dest[currentByte] & (~upMask));
//merge bytes~
dest[currentByte] = (byte)(dest[currentByte] | currentBits);
//System.out.println("new currentByte: " + dest[currentByte]);
count -= bitRoom;
currentOffset = 0;
currentByte++;
}
}
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::packInt: End");
}
/**
* Pack a number of bits from each int of an array(within given limits)to
* the end of this list.
*
* @param inputA Array containing input values.
* @param inputBits Array containing number of bits to use for each index
* packed. This array should be equal in size to the inputA array.
* @param inputOffset Index of first usable index.
* @param countA Number of indices to pack.
* @param startPosIn First usable bit-level index in destination array(byte
* index = startPosIn/8, bit within that byte = startPosIn%8)
* @param dest Destination array to store input values in. This array *must*
* be large enough to store all values or this method will fail in an
* undefined manner.
*/
public static void packIntByBits(int[] inputA, int[] inputBits, int inputOffset,
int countA, int startPosIn, byte[] dest) {
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::packIntByBits : Begin");
//int offsetCounter = 0;
int inputIter = 0;
int startPos = startPosIn;//the position to write to in output array
inputIter = inputOffset;
int inputStop = countA+inputOffset;
for(int valI = inputOffset; valI < inputStop; valI++) {
//inputIter = valI+inputOffset;
//inputIter += valI;
int input = inputA[valI];//value to encode
int count = inputBits[valI];//bits of value to encode
//int startPos = startPosIn+offsetCounter;//the write bit position
//offsetCounter += count;
int currentByte = startPos/8;
int currentOffset = startPos%8;
startPos += count;//startPos must not be referenced again below here!
int bitRoom;//how many bits can be placed in current byte
int upMask;//to clear upper bits(lower bits auto-cleared by L-shift
int downShift;//bits to shift down, isolating top bits of input
int upShift;//bits to shift up, packing byte from top.
if(currentOffset != 0) {
bitRoom = 8-currentOffset;
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
downShift = count-bitRoom;
upMask = 255 >>> currentOffset;
upShift = 0;
if(downShift < 0) {
//upMask = 255 >>> bitRoom-count;
upShift = bitRoom - count;
upMask = 255 >>> (currentOffset+upShift);
downShift = 0;
}
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
int currentBits = (input >>> downShift) & (upMask);
//shift bits back up to match offset
currentBits = currentBits << upShift;
upMask = (byte)upMask << upShift;
dest[currentByte] = (byte)(dest[currentByte] & (~upMask));
//merge bytes~
dest[currentByte] = (byte)(dest[currentByte] | currentBits);
//System.out.println("new currentByte: " + dest[currentByte]);
count -= bitRoom;
currentOffset = 0;
currentByte++;
}
bitRoom = 8;
upShift = 0;
upMask = 255;
while(count >= 8) {
//find how many bits can be placed in current byte
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
downShift = count-bitRoom;
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
int currentBits = (input >>> downShift) & (upMask);
dest[currentByte] = (byte)currentBits;
count -= bitRoom;
currentByte++;
}
if(count > 0) {//while(count > 0) {
//find how many bits can be placed in current byte
//bitRoom = 8-currentOffset;
//get those bits
//i.e, take upper 'bitsNeeded' of input, put to lower part of byte.
//downShift = count-bitRoom;
downShift = 0;
upShift = bitRoom - count;
upMask = 255 >>> upShift;
if(DEBUG_LEV > 30) {
System.err.println("count:offset:bitRoom:downShift:upShift:" +
count+":"+currentOffset+":"+bitRoom+":"+downShift+":"+upShift);
}
// int currentBits = (input >>> downShift) & (upMask);
int currentBits = input & upMask;
//shift bits back up to match offset
currentBits = currentBits << upShift;
upMask = (byte)upMask << upShift;
dest[currentByte] = (byte)(dest[currentByte] & (~upMask));
//merge bytes~
dest[currentByte] = (byte)(dest[currentByte] | currentBits);
//System.out.println("new currentByte: " + dest[currentByte]);
count -= bitRoom;
currentOffset = 0;
currentByte++;
}
}
if(DEBUG_LEV > 30)
System.err.println("EncodedElement::addInt : End");
}
/**
* Force the usable data stored in this list ends on a a byte boundary, by
* padding to the end with zeros.
*
* @return true if the data was padded, false if it already ended on a byte
* boundary.
*/
public boolean padToByte() {
boolean padded = false;
//System.err.println("Usable bits: "+tempVal);
EncodedElement end = EncodedElement.getEnd_S(this);
int tempVal = end.usableBits;
if(tempVal % 8 != 0) {
int toWrite = 8-(tempVal%8);
end.addInt(0, toWrite);
/* FOR DEVEL ONLY: */
if( (this.getTotalBits()+offset) % 8 != 0)
System.err.println("EncodedElement::padToByte: SERIOUS ERROR! " +
"Algorithm implemented is incorrect!!!");
padded = true;
}
return padded;
}
}