mirror of
https://github.com/AppleCommander/ShrinkItArchive.git
synced 2024-12-22 02:31:00 +00:00
Adding LittleEndianByteOutputStream.
This commit is contained in:
parent
048f640e81
commit
c188bf6c2b
124
src/com/webcodepro/shrinkit/io/LittleEndianByteOutputStream.java
Normal file
124
src/com/webcodepro/shrinkit/io/LittleEndianByteOutputStream.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package com.webcodepro.shrinkit.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import com.webcodepro.shrinkit.CRC16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An OutputStream with helper methods to write little endian numbers
|
||||||
|
* and other Apple-specific tidbits.
|
||||||
|
*
|
||||||
|
* @author robgreene@users.sourceforge.net
|
||||||
|
*/
|
||||||
|
public class LittleEndianByteOutputStream extends OutputStream implements ByteConstants {
|
||||||
|
private OutputStream outputStream;
|
||||||
|
private long bytesWritten = 0;
|
||||||
|
private CRC16 crc = new CRC16();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a LittleEndianByteOutputStream from an OutputStream.
|
||||||
|
*/
|
||||||
|
public LittleEndianByteOutputStream(OutputStream outputStream) {
|
||||||
|
this.outputStream = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a next byte.
|
||||||
|
*/
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
outputStream.write(b);
|
||||||
|
crc.update(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the NuFile id to the LittleEndianByteOutputStream.
|
||||||
|
*/
|
||||||
|
public void writeNuFileId() throws IOException {
|
||||||
|
write(NUFILE_ID);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write the NuFX id to the LittleEndianByteOutputStream.
|
||||||
|
*/
|
||||||
|
public void writeNuFxId() throws IOException {
|
||||||
|
write(NUFX_ID);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write a "Word".
|
||||||
|
*/
|
||||||
|
public void writeWord(int w) throws IOException {
|
||||||
|
write(w & 0xff);
|
||||||
|
write(w >> 8);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write a "Long".
|
||||||
|
*/
|
||||||
|
public void writeLong(long l) throws IOException {
|
||||||
|
write((int)(l & 0xff));
|
||||||
|
write((int)((l >> 8) & 0xff));
|
||||||
|
write((int)((l >> 16) & 0xff));
|
||||||
|
write((int)((l >> 24) & 0xff));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write the Java Date object as a TimeRec.
|
||||||
|
* Note that years 2000-2039 are assumed to be 00-39 per the NuFX addendum
|
||||||
|
* at http://www.nulib.com/library/nufx-addendum.htm.
|
||||||
|
* @see http://www.nulib.com/library/nufx-addendum.htm
|
||||||
|
*/
|
||||||
|
public void writeDate(Date date) throws IOException {
|
||||||
|
byte[] data = null;
|
||||||
|
if (date == null) {
|
||||||
|
data = TIMEREC_NULL;
|
||||||
|
} else {
|
||||||
|
data = new byte[TIMEREC_LENGTH];
|
||||||
|
GregorianCalendar gc = new GregorianCalendar();
|
||||||
|
gc.setTime(date);
|
||||||
|
int year = gc.get(Calendar.YEAR);
|
||||||
|
year -= (year < 2000) ? 1900 : 2000;
|
||||||
|
data[TIMEREC_YEAR] = (byte)(year & 0xff);
|
||||||
|
data[TIMEREC_MONTH] = (byte)(gc.get(Calendar.MONTH) + 1);
|
||||||
|
data[TIMEREC_DAY] = (byte)gc.get(Calendar.DAY_OF_MONTH);
|
||||||
|
data[TIMEREC_HOUR] = (byte)gc.get(Calendar.HOUR_OF_DAY);
|
||||||
|
data[TIMEREC_MINUTE] = (byte)gc.get(Calendar.MINUTE);
|
||||||
|
data[TIMEREC_SECOND] = (byte)gc.get(Calendar.SECOND);
|
||||||
|
data[TIMEREC_WEEKDAY] = (byte)gc.get(Calendar.DAY_OF_WEEK);
|
||||||
|
}
|
||||||
|
write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the CRC-16 to $0000.
|
||||||
|
*/
|
||||||
|
public void resetCrc() {
|
||||||
|
crc.reset();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the current CRC-16 value.
|
||||||
|
*/
|
||||||
|
public long getCrcValue() {
|
||||||
|
return crc.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer with the total number of bytes written.
|
||||||
|
*/
|
||||||
|
public long getTotalBytesWritten() {
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass the flush request to the wrapped stream.
|
||||||
|
*/
|
||||||
|
public void flush() throws IOException {
|
||||||
|
outputStream.flush();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Pass the close request to the wrapped stream.
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package com.webcodepro.shrinkit.io;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exercise the LittleEndianByteOutputStream class.
|
||||||
|
* @author robgreene@users.sourceforge.net
|
||||||
|
*/
|
||||||
|
public class LittleEndianByteOutputStreamTest extends TestCaseHelper {
|
||||||
|
public void testWriteA() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.write('a');
|
||||||
|
bs.close();
|
||||||
|
assertEquals("a".getBytes(), os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteB() throws IOException {
|
||||||
|
// Just to ensure we can write chunks of bytes...
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.write("hello".getBytes());
|
||||||
|
bs.close();
|
||||||
|
assertEquals("hello".getBytes(), os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteNuFileId() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeNuFileId();
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { 0x4e, (byte)0xf5, 0x46, (byte)0xe9, 0x6c, (byte)0xe5 }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testCheckNuFxId() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeNuFxId();
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { 0x4e, (byte)0xf5, 0x46, (byte)0xd8 }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteWord() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeWord(0x201);
|
||||||
|
bs.writeWord(0x403);
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { 0x01, 0x02, 0x03, 0x04 }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteWordHighBitSet() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeWord(0xffff);
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { (byte)0xff, (byte)0xff }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteLong() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeLong(0x04030201);
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { 0x01, 0x02, 0x03, 0x04 }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteLongHighBitSet() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeLong(0xffffffffL);
|
||||||
|
bs.close();
|
||||||
|
assertEquals(new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff }, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteDate() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeDate(new GregorianCalendar(1988, Calendar.OCTOBER, 22, 1, 10, 0).getTime());
|
||||||
|
bs.writeDate(new GregorianCalendar(1988, Calendar.NOVEMBER, 17, 11, 16, 0).getTime());
|
||||||
|
bs.writeDate(new GregorianCalendar(1988, Calendar.OCTOBER, 22, 13, 12, 0).getTime());
|
||||||
|
bs.close();
|
||||||
|
byte[] expected = new byte[] {
|
||||||
|
// From NuFX documentation, final revision 3
|
||||||
|
0x00, 0x0a, 0x01, 0x58, 0x16, 0x0a, 0x00, 0x07, // 01:10:00am 10/22/1988 saturday
|
||||||
|
0x00, 0x10, 0x0b, 0x58, 0x11, 0x0b, 0x00, 0x05, // 11:16:00am 11/17/1988 thursday
|
||||||
|
0x00, 0x0c, 0x0d, 0x58, 0x16, 0x0a, 0x00, 0x07, // 01:12:00pm 10/22/1988 saturday
|
||||||
|
};
|
||||||
|
assertEquals(expected, os.toByteArray());
|
||||||
|
}
|
||||||
|
public void testWriteNullDate() throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
LittleEndianByteOutputStream bs = new LittleEndianByteOutputStream(os);
|
||||||
|
bs.writeDate(null);
|
||||||
|
bs.close();
|
||||||
|
byte[] expected = new byte[] {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // null date
|
||||||
|
};
|
||||||
|
assertEquals(expected, os.toByteArray());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user