Copyright (c) Hyperion Entertainment and contributors.

Writing IFF

From AmigaOS Documentation Wiki
Revision as of 22:39, 15 April 2013 by Steven Solie (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Writing IFF Files

IFFParse provides facilities for writing IFF files. Again, IFFParse makes no assumptions about the data you’re writing, and concerns itself with verifying the syntax of your output.

Creating Chunks in a File

Because the IFF specification has nesting and scoping rules, you can nest chunks inside one another. One instance is the BMHD chunk, which is commonly nested inside a FORM chunk. Thus, it is necessary for you to inform IFFParse when you are starting and ending chunks.

PushChunk()

To tell IFFParse you are about to begin writing a new chunk, you use the function PushChunk():

error = IIFFParse->PushChunk(iff, ID_ILBM, ID_BMHD,chunksize);

The chunk ID and size are written to the stream. IFFParse will enforce the chunk size you specified; attempts to write past the end of the chunk will be truncated. If, as a chunk size argument, you pass IFFSIZE_UNKNOWN, the chunk will be expanded in size as you write data to it.

PopChunk()

When you are through writing data to a chunk, you complete the write by calling PopChunk():

error = IIFFParse->PopChunk(iff);

If you wrote fewer bytes than you declared with PushChunk(), PopChunk() will return an error. If you specified IFFSIZE_UNKNOWN, PopChunk() will seek backward on the stream and write the final size. If you specified a chunk size that was odd, PopChunk() will write the pad byte automatically.

PushChunk() and PopChunk() nest; every call to PushChunk() must have a corresponding call to PopChunk().

Writing Chunk Data

Writing the IFF chunk data is done with either the WriteChunkBytes() or WriteChunkRecords() functions.

error = IIFFParse->WriteChunkBytes(iff, buf, size);
error = IIFFParse->WriteChunkRecords(iff, buf, recsize, numrec);

If you specified a valid chunk size when you called PushChunk(), WriteChunkBytes() and WriteChunkRecords() will truncate attempts to write past the end of the chunk.

Code to write an ILBM file might take the following form:

iff = IIFFParse->AllocIFF ();
iff->iff_Stream = IDOS->Open ("foo", MODE_NEWFILE);
IIFFParse->InitIFFasDOS (iff);
IIFFParse->OpenIFF (iff, IFFF_WRITE);
 
IIFFParse->PushChunk (iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);
 
IIFFParse->PushChunk (iff, ID_ILBM, ID_BMHD, sizeof (struct BitMapHeader));
IIFFParse->WriteChunkBytes (iff, &bmhd, sizeof (bmhd));
IIFFParse->PopChunk (iff);
 
IIFFParse->PushChunk (iff, ID_ILBM, ID_CMAP, cmapsize);
IIFFParse->WriteChunkBytes (iff, cmapdata, cmapsize);
IIFFParse->PopChunk (iff);
 
IIFFParse->PushChunk (iff, ID_ILBM, ID_BODY, IFFSIZE_UNKNOWN);
packwritebody (iff);
IIFFParse->PopChunk (iff);
 
IIFFParse->PopChunk (iff);
 
IIFFParse->CloseIFF (iff);
IDOS->Close (iff->iff_Stream);
IIFFParse->FreeIFF (iff);

Again, error checking is not present for clarity. See the example code ClipFTXT.c which writes a simple FTXT clip to the clipboard.

A Note on Seekability

As you can see from the above examples, IFFParse works best with a stream that can seek randomly. However, it is not possible to seek on some streams (e.g., pipes).

IFFParse will read and write streams with limited or no seek capability. In the case of reading, only forward-seek capability is desirable. Failing this, IFFParse will fake forward seeks with a number of short reads.

In the case of writing, if the stream lacks random seek capability, IFFParse will buffer the entire contents of the file until you do the final PopChunk(), or when you CloseIFF() the handle. At that time, the entire stream will be written in one go. This buffering happens whether or not you specify all the chunk sizes to PushChunk().

About the Internal Buffering
The current implementation of this internal buffering could be more efficient. Be aware that the AmigaOS development team reserves the right to alter this behavior of the parser, to improve performance or reduce memory requirements. We mention this behavior on the off chance it is important to you.