public class IFFParser
extends java.lang.Object
Design Pattern
Design Role
Responsibility
Abstract
"EA IFF 85" is the standard interchange file format on Commodore Amiga Computers. An IFF File is built up of primitive data types, local chunks and group chunks.
The format for primitive data types is the same as used by the Motorola MC68000 processor. The high byte and high word of a number are stored first. All primitives larger than one byte are aligned on even byte addresses relative to the start of the file. Zeros should be stored in all the pad bytes. Characters and strings are usually coded according to ISO/DIS 6429.2 and ANSI X3.64-1979.
Data objects are built up with information blocks (or C structs) called local chunks.
IFF supports the three different kinds called 'data chunk', 'property chunk',
'collection chunk'.
Data chunks contain the essential information that build up an object, say the bitmap
data of a picture or the text of a document.
Property chunks specify attributes for following data chunks.
A property chunk essentially says "identifier=value". When designing an object, property
chunks do describe context information like the size of an image or the
color of the text. Specifying the same property chunk more then once overrides the previous
setting.
Collection chunks describe a property that can occur multiple times. All occurences
of a collection chunk must be collected within the scope of the current group chunk.
Group chunks are full fledged selfcontained data objects. A FORM Group stands for a single data object where as a CAT Group stands for an untyped group of data objects. A LIST defines a group very much like CAT but also gives a scope for shared properties (stored in PROP Groups).
For more information refer to "Amiga ROM Kernel Reference Manual, Devices, Third Edition, Addison Wesley".
Grammar for IFF streams
IFFFile ::= 'FORM' FormGroup | 'CAT ' CatGroup | 'LIST' ListGroup
GroupChunk ::= FormGroup | CatGroup | ListGroup | PropGroup | IFFStream FormGroup ::= size FormType { ChunkID LocalChunk [pad] | 'FORM' FormGroup [pad] | 'LIST ' ListGroup [pad] | 'CAT ' CatGroup [pad] } CatGroup ::= size CatType { 'FORM' FormGroup [pad] | 'LIST ' ListGroup [pad] | 'CAT ' CatGroup [pad] } ListGroup ::= size ListType { 'PROP' PropGroup [pad] } { 'FORM' FormGroup [pad] | 'LIST' CatGroup [pad] | 'CAT ' ListGroup [pad] } PropGroup ::= size PropType { ChunkID PropertyChunk [pad] }
LocalChunk ::= DataChunk | CollectionChunk | PropertyChunk DataChunk ::= size struct CollectionChunk ::= size struct PropertyChunk ::= size struct
size ::= ULONG FormType ::= ULONG CatType ::= ULONG ListType ::= ULONG PropType ::= ULONG ChunkID ::= ULONG pad ::= a single byte of value 0. struct ::= any C language struct built with primitive data types.
Examples
Traversing the raw structure of an IFF file
To traverse the file structure you must first set up an IFFVisitor object that does something useful at each call to the visit method. Then create an instance of IFFParser and invoke the #interpret method.
class IFFRawTraversal . { . static class Visitor . implements IFFVisitor . { . ...implement the visitor interface here... . } . . public static void main(String[] args) . { . try { . Visitor visitor = new Visitor(); . FileInputStream stream = new FileInputStream(args[0]); . IFFParser p = new IFFParser(); . p.interpret(stream,visitor); . stream.close(); . } . catch (IOException e) { System.out.println(e); } . catch (InterpreterException e) { System.out.println(e); } . catch (AbortedException e) { System.out.println(e); } . } . }
Traversing the IFF file and interpreting its content.
Since IFF files are not completely self describing (there is no information that helps differentiate between data chunks, property chunks and collection chunks) a reader must set up the interpreter with some contextual information before starting the interpreter.
Once at least one chunk has been declared, the interpreter will only call the
visitor for occurences of the declared group chunks and data chunks. The property
chunks and the collection chunks can be obtained from the current group chunk
by calling #getProperty or #getCollection.
Note: All information the visitor can obtain during interpretation is only
valid during the actual #visit... call. Dont try to get information about properties
or collections for chunks that the visitor is not visiting right now.
class InterpretingAnILBMFile . { . static class Visitor . implements IFFVisitor . { . ... . } . . public static void main(String[] args) . { . try { . Visitor visitor = new Visitor(); . FileInputStream stream = new FileInputStream(args[0]); . IFFParser p = new IFFParser(); . p.declareGroupChunk('FORM','ILBM'); . p.declarePropertyChunk('ILBM','BMHD'); . p.declarePropertyChunk('ILBM','CMAP'); . p.declareCollectionChunk('ILBM','CRNG'); . p.declareDataChunk('ILBM','BODY'); . p.interpret(stream,visitor); . stream.close(); . } . catch (IOException e) { System.out.println(e); } . catch (InterpreterException e) { System.out.println(e); } . catch (AbortedException e) { System.out.println(e); } . } . }
IFFVisitor
Modifier and Type | Field and Description |
---|---|
static int |
ID_CAT
ID for CATGroupExpression.
|
static int |
ID_FILLER
ID for unlabeled CATGroupExpressions.
|
static int |
ID_FORM
ID for FORMGroupExpression.
|
static int |
ID_LIST
ID for CATGroupExpression.
|
static int |
ID_PROP
ID for PROPGroupExpression.
|
static int[] |
RESERVED_IDs
The reserved group IDs "LIST", "FORM", "PROP", "CAT ", " ",
"LIS1" through "LIS9", "FOR1" through "FOR9" and "CAT1" through "CAT9"
may not be used for type IDs and for local chunk IDs.
|
Constructor and Description |
---|
IFFParser()
Constructs a new IFF parser.
|
Modifier and Type | Method and Description |
---|---|
void |
declareCollectionChunk(int type,
int id)
Declares a collection chunk.
|
void |
declareDataChunk(int type,
int id)
Declares a data chunk.
|
void |
declareGroupChunk(int type,
int id)
Declares a FORM group chunk.
|
void |
declarePropertyChunk(int type,
int id)
Declares a property chunk.
|
static java.lang.String |
idToString(int anID)
Convert an integer IFF identifier to String.
|
protected boolean |
isCollectionChunk(IFFChunk chunk)
Checks wether the ID of the chunk has been declared as a
collection chunk.
|
static boolean |
isContentType(int id)
Returns wether the argument is a valid Content Type ID.
|
protected boolean |
isDataChunk(IFFChunk chunk)
Checks whether the ID of the chunk has been declared as a
data chunk.
|
static boolean |
isFormType(int id)
Returns wether the argument is a valid FormType.
|
protected boolean |
isGroupChunk(IFFChunk chunk)
Checks wether the ID of the chunk has been declared as
a group chunk.
|
static boolean |
isGroupID(int id)
Checks wether the argument represents a valid IFF GroupID.
|
static boolean |
isID(int id)
Checks if the argument represents a valid IFF ID.
|
static boolean |
isLocalChunkID(int id)
Returns whether the argument is a valid Local Chunk ID.
|
protected boolean |
isPropertyChunk(IFFChunk chunk)
Checks wether the ID of the chunk has been declared as a
property chunk.
|
static boolean |
isReservedID(int id) |
void |
parse(java.io.InputStream in,
IFFVisitor v)
Interprets the IFFFileExpression located at the
current position of the indicated InputStream.
|
static int |
stringToID(java.lang.String aString)
Converts the first four letters of the
String into an IFF Identifier.
|
public static final int ID_FORM
public static final int ID_CAT
public static final int ID_LIST
public static final int ID_PROP
public static final int ID_FILLER
public static final int[] RESERVED_IDs
public void parse(java.io.InputStream in, IFFVisitor v) throws ParseException, AbortException, java.io.IOException
Pre condition
Post condition
Obligation The visitor may throw an ParseException or an AbortException during tree traversal.
ParseException
- Is thrown when an interpretation error occured.
The stream is positioned where the error occured.AbortException
- Is thrown when the visitor decided to abort the
interpretation.java.io.IOException
protected boolean isDataChunk(IFFChunk chunk)
Pre condition
chunk
- Chunk to be verified.protected boolean isGroupChunk(IFFChunk chunk)
Pre condition
chunk
- Chunk to be verified.protected boolean isPropertyChunk(IFFChunk chunk)
Pre condition
protected boolean isCollectionChunk(IFFChunk chunk)
Pre condition
chunk
- Chunk to be verified.public void declareDataChunk(int type, int id)
Pre condition
Post condition
type
- Type of the chunk. Must be formulated as a TypeID conforming
to the method #isFormType.id
- ID of the chunk. Must be formulated as a ChunkID conforming
to the method #isLocalChunkID.public void declareGroupChunk(int type, int id)
Pre condition
Post condition
type
- Type of the chunk. Must be formulated as a TypeID conforming
to the method #isFormType.id
- ID of the chunk. Must be formulated as a ChunkID conforming
to the method #isContentsType.public void declarePropertyChunk(int type, int id)
Pre condition
Post condition
type
- Type of the chunk. Must be formulated as a TypeID conforming
to the method #isFormType.id
- ID of the chunk. Must be formulated as a ChunkID conforming
to the method #isLocalChunkID.public void declareCollectionChunk(int type, int id)
Pre condition
Post condition
type
- Type of the chunk. Must be formulated as a TypeID conforming
to the method #isFormType.id
- ID of the chunk. Must be formulated as a ChunkID conforming
to the method #isLocalChunkID.public static boolean isGroupID(int id)
Validation
id
- Chunk ID to be checked.public static boolean isID(int id)
Validation
id
- Chunk ID to be checked.public static boolean isLocalChunkID(int id)
Validation
id
- Chunk ID to be checked.public static boolean isReservedID(int id)
public static boolean isFormType(int id)
Validation:
id
- Chunk ID to be checked.public static boolean isContentType(int id)
Validation
id
- Chunk ID to be checked.public static java.lang.String idToString(int anID)
anID
- ID to be converted.public static int stringToID(java.lang.String aString)
aString
- String to be converted.