
org.monte.media.iff.MutableIFFChunk Maven / Gradle / Ivy
/*
* @(#)MutableIFFChunk.java 1.0 December 25, 2006
*
* Copyright (c) 2006 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.media.iff;
import java.io.*;
import java.util.*;
import javax.swing.tree.*;
/**
* MutableIFFChunk.
*
* Syntax of an IFF Chunk:
*
* Chunk ::= ID #{ UBYTE* } [0]
*
* Property ::= Chunk
*
* FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* }
* FormType ::= ID
* LocalChunk ::= Property | Chunk
*
* CAT ::= "CAT " #{ ContentsType {FROM | LIST | CAT)* }
* ContentsType ::= ID -- a hint or an "abstract data type" ID
*
* LIST ::= "LIST" #{ ContentsType PROP* {FORM | LIST | CAT)* }
* PROP ::= "PROP" #{ FormType Property* }
*
* In this extended regular expression notation the token "#" represents
* a count of the following braced data types. Literal items are shown in
* "quotes", [square bracketed items] are optional, and "*" means 0 or more
*instances. A sometimes-needed pad is shown as "[0]".
*
*
* @author Werner Randelshofer
* @version 1.0 December 25, 2006 Created.
*/
public class MutableIFFChunk extends DefaultMutableTreeNode {
/** ID for FORMGroupExpression. */
public final static int ID_FORM = 0x464f524d;
/** ID for CATGroupExpression. */
public final static int ID_CAT = 0x43415420;
/** ID for CATGroupExpression. */
public final static int ID_LIST = 0x4c495354;
/** ID for PROPGroupExpression. */
public final static int ID_PROP = 0x50524f50;
/** ID for unlabeled CATGroupExpressions. */
public final static int ID_FILLER = 0x20202020;
/**
* The type of an IFF Chunk.
*/
private int type;
/**
* The id of an IFF Chunk.
*/
private int id;
/**
* The dat of an IFF Chunk.
*/
private byte[] data;
/** Creates a new instance. */
public MutableIFFChunk() {
}
/** Creates a new instance. */
public MutableIFFChunk(int id, int type) {
this.id = id;
this.type = type;
}
/** Creates a new instance. */
public MutableIFFChunk(int id, byte[] data) {
this.id = id;
this.data = data;
}
/** Creates a new instance. */
public MutableIFFChunk(String id, String type) {
this.id = stringToId(id);
this.type = stringToId(type);
}
/** Creates a new instance. */
public MutableIFFChunk(String id, byte[] data) {
this.id = stringToId(id);
this.data = data;
}
public void setType(int newValue) {
int oldValue = type;
type = newValue;
}
public void setId(int newValue) {
int oldValue = id;
id = newValue;
}
public void setData(byte[] newValue) {
byte[] oldValue = data;
data = newValue;
}
public int getType() {
return type;
}
public int getId() {
return id;
}
public byte[] getData() {
return data;
}
public int getLength() {
if (data != null) {
return data.length;
} else {
int length = 4;
for (MutableIFFChunk child : childChunks()) {
int childLength = child.getLength();
length += 8 + childLength + childLength % 2;
}
return length;
}
}
public Vector childChunks() {
return (children == null) ? new Vector(0) : new Vector(children);
}
public String dump() {
return dump(0);
}
public String dump(int depth) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < depth; i++) {
buf.append('.');
}
buf.append(idToString(getId()));
buf.append(' ');
buf.append(getLength());
if (getChildCount() > 0) {
buf.append(' ');
buf.append(idToString(getType()));
for (MutableIFFChunk child : childChunks()) {
buf.append('\n');
buf.append(child.dump(depth + 1));
}
}
return buf.toString();
}
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(idToString(getId()));
buf.append(' ');
buf.append(getLength());
if (data == null) {
buf.append(' ');
buf.append(idToString(getType()));
}
return buf.toString();
}
/**
* Convert an integer IFF identifier to String.
*
* @param anID to be converted.
* @return String representation of the ID.
*/
public static String idToString(int anID) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (anID >>> 24);
bytes[1] = (byte) (anID >>> 16);
bytes[2] = (byte) (anID >>> 8);
bytes[3] = (byte) (anID >>> 0);
return new String(bytes);
}
/**
* Converts the first four letters of the
* String into an IFF Identifier.
*
* @param aString String to be converted.
* @return ID representation of the String.
*/
public static int stringToId(String aString) {
byte[] bytes = aString.getBytes();
return ((int) bytes[0]) << 24 |
((int) bytes[1]) << 16 |
((int) bytes[2]) << 8 |
((int) bytes[3]) << 0;
}
public void read(File f) throws IOException {
MC68000InputStream in = new MC68000InputStream(
new BufferedInputStream(
new FileInputStream(f)));
try {
read(in);
} finally {
in.close();
}
}
public void read(MC68000InputStream in) throws IOException {
id = in.readLONG();
long length = in.readULONG();
switch (id) {
case ID_CAT:
case ID_FORM:
case ID_LIST:
case ID_PROP:
type = in.readLONG();
length -= 4;
while (length > 1) {
MutableIFFChunk child = new MutableIFFChunk();
child.read(in);
add(child);
int childLength = child.getLength();
length -= childLength + childLength % 2 + 8;
}
break;
default:
data = new byte[(int) length];
in.readFully(data, 0, (int) length);
break;
}
if (length % 2 == 1) {
in.read();
}
}
public void Write(File f) throws IOException {
MC68000OutputStream out = new MC68000OutputStream(
new BufferedOutputStream(
new FileOutputStream(f)));
try {
write(out);
} finally {
out.close();
}
}
public void write(MC68000OutputStream out) throws IOException {
out.writeULONG(id);
long length = getLength();
out.writeULONG(length);
if (data == null) {
out.writeULONG(type);
for (MutableIFFChunk child : childChunks()) {
child.write(out);
}
} else {
out.write(data);
}
if (length % 2 == 1) {
out.write((byte) 0);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy