/**
* This class is released under GNU GENERAL PUBLIC LICENSE.
*
* Wraps byte information, displays it in four different bases - binary, ASCII, decimal and hexadecimal. Preserves the four values, so no
* recalculation occurs during displaying if value hasn't changed. Also parses the value from String form if needed.
* Pros:
* +No additional calculations are needed when frequent converting from one base to another is needed.
* It's done once after the value is changed.
* +Binary String is held in its 8-bit user-friendly form. Great for displaying or bit-editing.
* +All the information is in one tidy class, no additional variables are needed to hold information.
* +Efficient and safe single bit flipping.
* Cons:
* -Tests show that recalculation is a little bit slower than implementing the whole thing separately,
* using purely Integer's own methods. But the difference is minimal, in about 2 million value changes
* my computer generated about 300ms difference. (0.469 / 0.765)seconds accordingly. Most of this is thanks
* to the binary String concatenation (filling the '0's in front of the String to get 8 bits).
*
*
* Total memory usage for instanced object is 2 integers + 4 short Strings in an array
*
* @author Joonas Vali, 2010 September
*
*/
public class MByte extends Number implements Comparable<Number>{
/**
* 1L: 14.09.2010
*/
private static final long serialVersionUID = 1L;
private int value;
private int hash;
private static String[] binFill = {"", "0", "00", "000", "0000", "00000", "000000", "0000000", "00000000"};
private String[] cache;
public static final int BINARY = 0, ASCII = 1, DECIMAL = 2, HEXADECIMAL = 3;
public static final int NUMBER_OF_TYPES = 4;
/**
* Create a new wrapper for a byte.
* @param value the decimal value of byte to be wrapped.
* currently existing: BINARY, ASCII, DECIMAL and HEXADECIMAL
* * @throws IllegalArgumentException when byte is out of range(unsigned byte range)
*/
public MByte(int value){
if(value < 0 || value > 255) throw new IllegalArgumentException("Byte value out of range: "+value);
this.value = value;
cache = new String[NUMBER_OF_TYPES];
fillCache();
}
/**
* Calculates and fills the 'cache' with right Strings from the decimal value
*/
private void fillCache(){
String str = Integer.toBinaryString(value);
cache[BINARY] = binFill[8- str.length()]+str;
cache[ASCII] = Character.toString((char)value);
cache[DECIMAL] = Integer.toString(value);
cache[HEXADECIMAL] = Integer.toString(value, 16);
hash = ((Integer)value).hashCode();
}
/**
* @return a String based on the currently set type. Binary is always 8 digits, for bit editing purposes
*/
public String toString(int type){
if(type > NUMBER_OF_TYPES || type < 0) throw new IllegalArgumentException("Type out of range");
return cache[type];
}
/**
* @return the String of the decimal value
*/
public String toString(){
return cache[DECIMAL];
}
/**
* set a new value
* @param value must be corresponding value to the type for parsing.
* @param type must be corresponding to the value for parsing.
* @throws IllegalArgumentException if unfit value was inserted for a type, or type is out of range.
*/
public void setValue(String value, int type){
int oldValue = this.value;
if(type > NUMBER_OF_TYPES || type < 0) throw new IllegalArgumentException("Type out of range");
try{
switch(type){
case BINARY: this.value = Integer.parseInt(value,2); break;
case ASCII: this.value = (int)value.charAt(0); break;
case DECIMAL: this.value = Integer.parseInt(value); break;
case HEXADECIMAL: this.value = Integer.parseInt(value, 16);
}
if(oldValue != this.value)fillCache();
} catch(Exception e){
throw new IllegalArgumentException("Incorrect value("+value+") for specified type. Exception:\n"+e);
}
}
/**
* Flip single bits. Index count starts from the end.
* @param index the index of the bit to be switched 0-7. 0 is the rightmost bit
* @param direction the direction of flip, true is for 1 and false is for 0.
* if bit is already in the direction, then nothing happens.
* @throws IllegalArgumentException if index is out of bounds
*/
public void flipBit(int index, boolean direction){
if(index > 7 || index < 0)throw new IllegalArgumentException("Index needs to be between 0-7");
int oldvalue = value;
value = direction ? value | (int)Math.pow(2, index) : value &~ (int)Math.pow(2, index);
if(oldvalue != value)fillCache();
}
/**
* set a new value
* @param value A decimal value within a range of byte
* @throws IllegalArgumentException when value is out of range (unsigned byte range)
*/
public void setValue(int value){
if(value < 0 || value > 255) throw new IllegalArgumentException("Byte value out of range: "+value);
if(this.value == value) return;
this.value = value;
fillCache();
}
/**
* Checks the equality with another object. Comparison can be done with any object of the
* same kind or any object extending the Number Class. Only the actual value will be considered.
* @return true in case values are equal
*/
@Override
public boolean equals(Object other){
if(other instanceof Number && ((Number)other).intValue() == value) return true;
return false;
}
/**
* Compares this object with another object. Comparison can be done with any object extending the Number Class,
* including this. Only the numerical value will be considered.
* @return the value 0 if this object is equal to the argument's numerical value; a value less than 0 if this
* object is numerically less than the argument's numerical value; and a value greater than 0 if this object
* is numerically greater than the argument's numerical value (signed comparison).
*/
@Override
public int compareTo(Number number) {
return ((Integer)this.value).compareTo(number.intValue());
}
/**
* @return a hashcode calculated based on the numerical value
*/
@Override
public int hashCode(){
return hash;
}
/**
* Get the current value
* @return the value in decimal and as a double
*/
@Override
public double doubleValue() {
return (double)value;
}
/**
* Get the current value
* @return the value in decimal and as a float
*/
@Override
public float floatValue() {
return (float)value;
}
/**
* Get the current value
* @return the value in decimal and as an integer
*/
@Override
public int intValue() {
return value;
}
/**
* Get the current value
* @return the value in decimal and as a long
*/
@Override
public long longValue() {
return (long)value;
}
/**
* Get the current value
* @return the value in decimal and as a byte
*/
public byte byteValue() {
return (byte)value;
}
}
Edited by Sinipull, 15 September 2010 - 02:17 PM.
Added single bit flipping possibility


Sign In
Create Account


Back to top









