Overview | Package | Class | Tree | Deprecated | Index | Help
| Copyright 2012-04-26 Werner Randelshofer
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.monte.media.riff
Class RIFFParser

    java.lang.Object
      org.monte.media.riff.RIFFParser

    public class RIFFParser

extends java.lang.Object

Interprets Resource Interchange File Format (RIFF) streams.

Abstract

RIFF File Format A RIFF file consists of a RIFF header followed by zero or more lists and chunks.

The RIFF header has the following form:

     'RIFF' fileSize fileType (data)

where 'RIFF' is the literal FOURCC code 'RIFF', fileSize is a 4-byte value giving the size of the data in the file, and fileType is a FOURCC that identifies the specific file type. The value of fileSize includes the size of the fileType FOURCC plus the size of the data that follows, but does not include the size of the 'RIFF' FOURCC or the size of fileSize. The file data consists of chunks and lists, in any order.

FOURCCs
A FOURCC (four-character code) is a 32-bit unsigned integer created by concatenating four ASCII characters. For example, the FOURCC 'abcd' is represented on a Little-Endian system as 0x64636261. FOURCCs can contain space characters, so ' abc' is a valid FOURCC. The RIFF file format uses FOURCC codes to identify stream types, data chunks, index entries, and other information.

A chunk has the following form:

     ckID ckSize ckData

where ckID is a FOURCC that identifies the data contained in the chunk, ckData is a 4-byte value giving the size of the data in ckData, and ckData is zero or more bytes of data. The data is always padded to nearest WORD boundary. ckSize gives the size of the valid data in the chunk; it does not include the padding, the size of ckID, or the size of ckSize.

A list has the following form:

     'LIST' listSize listType listData

where 'LIST' is the literal FOURCC code 'LIST', listSize is a 4-byte value giving the size of the list, listType is a FOURCC code, and listData consists of chunks or lists, in any order. The value of listSize includes the size of listType plus the size of listData; it does not include the 'LIST' FOURCC or the size of listSize.

For more information see: http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/aboutriff.asp

Grammar for RIFF streams used by this parser

     RIFFFile    ::= 'RIFF' FormGroup

     GroupChunk  ::= FormGroup | ListGroup
     FormGroup   ::= size GroupType [ ChunkID LocalChunk [pad] | 'LIST ' ListGroup  [pad] }
     ListGroup   ::= size GroupType [ ChunkID LocalChunk [pad] | 'LIST ' ListGroup  [pad] }

     LocalChunk      ::= DataChunk | CollectionChunk | PropertyChunk
     DataChunk       ::= size [ struct ]
     CollectionChunk ::= size [ struct ]
     PropertyChunk   ::= size [ struct ]

     size        ::= ULONG
     GroupType   ::= FourCC
     ChunkID     ::= FourCC
     pad         ::= (BYTE)0
     struct      ::= any C language struct built with primitive data types.

Examples

Traversing the raw structure of a RIFF file

To traverse the file structure you must first set up a RIFFVisitor object that does something useful at each call to the visit method. Then create an instance of a RIFFParser and invoke the #interpret method.

     class RIFFRawTraversal
     .      {
     .      static class Visitor
     .      implements RIFFVisitor
     .              {
     .              ...implement the visitor interface here...
     .              }
     .
     .      public static void main(String[] args)
     .              {
     .              try     {
     .                      Visitor visitor = new Visitor();
     .                      FileInputStream stream = new FileInputStream(args[0]);
     .                      RIFFParser p = new RIFFParser();
     .                      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 RIFF file and interpreting its content.

Since RIFF 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 RIFFVisitor
     .              {
     .              ...
     .              }
     .
     .      public static void main(String[] args)
     .              {
     .              try     {
     .                      Visitor visitor = new Visitor();
     .                      FileInputStream stream = new FileInputStream(args[0]);
     .                      RIFFParser p = new RIFFParser();
     .                      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); }
     .              }
     .      }

Version:
  1.4 2011-08-26 Adds HashMap for stop chunks.
  1.3 2011-01-23 Use HashMap instead of Hashtable.
  1.2 2010-07-06 Use integer IDs for efficiency. Added support for stop chunks.
  1.0 2005-01-16 Created.
Author:
  Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
See Also:
  `RIFFVisitor`

Field Summary
`static int` | `JUNK_ID` ID for JUNK chunks.
`static int` | `LIST_ID` ID for ListGroupExpression.
`static int` | `NULL_ID` ID for NULL chunks.
`static int` | `NULL_NUL_ID` ID for NULL chunks.
`static int` | `RIFF_ID` ID for FormGroupExpression.

Constructor Summary
`RIFFParser()` Constructs a new RIFF parser.

Method Summary
`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.
`void` | `declareStopChunks()` Whether the parse should stop at all chunks.
`void` | `declareStopChunkType(int type)` Declares a stop chunk.
`static java.lang.String` | `idToString(int anInt)` Convert an integer IFF identifier to String.
`protected boolean` | `isCollectionChunk(RIFFChunk chunk)` Checks wether the ID of the chunk has been declared as a collection chunk.
`protected boolean` | `isDataChunk(RIFFChunk chunk)` Checks whether the ID of the chunk has been declared as a data chunk.
`protected boolean` | `isGroupChunk(RIFFChunk chunk)` Checks whether the ID of the chunk has been declared as a group chunk.
`static boolean` | `isGroupID(int id)` Checks wether the argument represents a valid RIFF GroupID.
`static boolean` | `isGroupType(int id)` Checks wether the argument represents a valid RIFF Group Type.
`static boolean` | `isID(int id)` Checks if the argument represents a valid RIFF ID.
`static boolean` | `isLocalChunkID(int id)` Returns whether the argument is a valid Local Chunk ID.
`protected boolean` | `isPropertyChunk(RIFFChunk chunk)` Checks wether the ID of the chunk has been declared as a property chunk.
`void` | `parse(javax.imageio.stream.ImageInputStream in, RIFFVisitor v)`
`long` | `parse(java.io.InputStream in, RIFFVisitor v)` Interprets the RIFFFile expression 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.

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Field Detail

### RIFF_ID

    public static final int RIFF_ID

  ID for FormGroupExpression.

### LIST_ID

    public static final int LIST_ID

  ID for ListGroupExpression.

### NULL_ID

    public static final int NULL_ID

  ID for NULL chunks.

### NULL_NUL_ID

    public static final int NULL_NUL_ID

  ID for NULL chunks.

### JUNK_ID

    public static final int JUNK_ID

  ID for JUNK chunks.

Constructor Detail

### RIFFParser

    public RIFFParser()

  Constructs a new RIFF parser.

Method Detail

### parse

    public long parse(java.io.InputStream in,
                      RIFFVisitor v)
               throws ParseException,
                      AbortException,
                      java.io.IOException

  Interprets the RIFFFile expression located at the current position of the indicated InputStream. Lets the visitor traverse the RIFF parse tree during interpretation.

  Pre condition

  - Data-, property- and collection chunks must have been declared prior to this call.
  - When the client never declared chunks, then all local chunks will be interpreted as data chunks.
  - The stream must be positioned at the beginning of the RIFFFileExpression.

    Post condition

  - When no exception was thrown then the stream is positioned after the RIFFFile expression.

    Obligation The visitor may throw an ParseException or an AbortException during tree traversal.

  Throws:
    `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`

### parse

    public void parse(javax.imageio.stream.ImageInputStream in,
                      RIFFVisitor v)
               throws ParseException,
                      AbortException,
                      java.io.IOException

  Throws:
    `ParseException`
    `AbortException`
    `java.io.IOException`

### isDataChunk

    protected boolean isDataChunk(RIFFChunk chunk)

  Checks whether the ID of the chunk has been declared as a data chunk.

  Pre condition

  - Data chunks must have been declared before the interpretation has been started.
  - This method will always return true when neither data chunks, property chunks nor collection chunks have been declared,

  Parameters:
    `chunk` - Chunk to be verified.
  Returns:
    True when the parameter is a data chunk.

### isGroupChunk

    protected boolean isGroupChunk(RIFFChunk chunk)

  Checks whether the ID of the chunk has been declared as a group chunk.

  Pre condition

  - Group chunks must have been declared before the interpretation has been started. (Otherwise the response is always true).

  Parameters:
    `chunk` - Chunk to be verified.
  Returns:
    True when the visitor is interested in this is a group chunk.

### isPropertyChunk

    protected boolean isPropertyChunk(RIFFChunk chunk)

  Checks wether the ID of the chunk has been declared as a property chunk.

  Pre condition

  - Property chunks must have been declared before the interpretation has been started.
  - This method will always return false when neither data chunks, property chunks nor collection chunks have been declared,

### isCollectionChunk

    protected boolean isCollectionChunk(RIFFChunk chunk)

  Checks wether the ID of the chunk has been declared as a collection chunk.

  Pre condition

  - Collection chunks must have been declared before the interpretation has been started.
  - This method will always return true when neither data chunks, property chunks nor collection chunks have been declared,

  Parameters:
    `chunk` - Chunk to be verified.
  Returns:
    True when the parameter is a collection chunk.

### declareDataChunk

    public void declareDataChunk(int type,
                                 int id)

  Declares a data chunk.

  Pre condition

  - The chunk must not have already been declared as of a different type.
  - Declarations may not be done during interpretation of an RIFFFileExpression.

    Post condition

  - Data chunk declared

  Parameters:
    `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.

### declareGroupChunk

    public void declareGroupChunk(int type,
                                  int id)

  Declares a FORM group chunk.

  Pre condition

  - The chunk must not have already been declared as of a different type.
  - Declarations may not be done during interpretation of an RIFFFileExpression.

    Post condition

  - Group chunk declared

  Parameters:
    `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.

### declarePropertyChunk

    public void declarePropertyChunk(int type,
                                     int id)

  Declares a property chunk.

  Pre condition

  - The chunk must not have already been declared as of a different type.
  - Declarations may not be done during interpretation of an RIFFFileExpression.

    Post condition

  - Group chunk declared

  Parameters:
    `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.

### declareCollectionChunk

    public void declareCollectionChunk(int type,
                                       int id)

  Declares a collection chunk.

  Pre condition

  - The chunk must not have already been declared as of a different type.
  - Declarations may not be done during interpretation of an RIFFFileExpression.

    Post condition

  - Collection chunk declared

  Parameters:
    `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.

### declareStopChunkType

    public void declareStopChunkType(int type)

  Declares a stop chunk.

  Pre condition

  - The chunk must not have already been declared as of a different type.
  - Declarations may not be done during interpretation of an RIFFFileExpression.

    Post condition

  - Stop chunk declared

  Parameters:
    `type` - Type of the chunk. Must be formulated as a TypeID conforming to the method #isFormType.

### declareStopChunks

    public void declareStopChunks()

  Whether the parse should stop at all chunks.

  The parser does not read the data body of stop chunks.

  By declaring stop chunks, and not declaring any data, group or property chunks, the file structure of a RIFF file can be quickly scanned through.

### isGroupID

    public static boolean isGroupID(int id)

  Checks wether the argument represents a valid RIFF GroupID.

  Validation

  - Group ID must be one of RIFF_ID, LIST_ID.

  Parameters:
    `id` - Chunk ID to be checked.
  Returns:
    True when the chunk ID is a valid Group ID.

### isGroupType

    public static boolean isGroupType(int id)

  Checks wether the argument represents a valid RIFF Group Type.

  Validation

  - Must be a valid ID.
  - Must not be a group ID.
  - Must not be a NULL_ID.

  Parameters:
    `id` - Chunk ID to be checked.
  Returns:
    True when the chunk ID is a valid Group ID.

### isID

    public static boolean isID(int id)

  Checks if the argument represents a valid RIFF ID.

  Validation

  - Every byte of an ID must be in the range of 0x20..0x7e
  - The id may not have leading spaces (unless the id is a NULL_ID).

  Parameters:
    `id` - Chunk ID to be checked.
  Returns:
    True when the ID is a valid IFF chunk ID.

### isLocalChunkID

    public static boolean isLocalChunkID(int id)

  Returns whether the argument is a valid Local Chunk ID.

  Validation

  - Must be valid ID.
  - Local Chunk IDs may not collide with GroupIDs.
  - Must not be a NULL_ID.

  Parameters:
    `id` - Chunk ID to be checked.
  Returns:
    True when the chunk ID is a Local Chunk ID.

### idToString

    public static java.lang.String idToString(int anInt)

  Convert an integer IFF identifier to String.

  Parameters:
    `anInt` - ID to be converted.
  Returns:
    String representation of the ID.

### stringToID

    public static int stringToID(java.lang.String aString)

  Converts the first four letters of the String into an IFF Identifier.

  Parameters:
    `aString` - String to be converted.
  Returns:
    ID representation of the String.

Overview | Package | Class | Tree | Deprecated | Index | Help
| Copyright 2012-04-26 Werner Randelshofer
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD