IFF フォーマットの概要
 
 
 

flib ライブラリの簡単な説明を次に記します。ここでは、IFF フォーマットに基づく汎用的な構造化ファイル アクセス機構を実装する flib ライブラリについて簡単に説明します。IFF は Maya のイメージとテクスチャで現在使用されているフォーマットです。

カーネル

ファイル タイプからの独立性

flib ライブラリの基本的な概念は、すべてのファイル アクセスを同じ方式で表現することです。ディスク ファイル、パイプ、メモリ セグメントなどが論理的にはすべてファイルとして表され、同じ関数集合を通じて操作されます。flib カーネルは、8 つの関数(FLopen、FLreopen、FLclose、FLread、FLwrite、FLseek、FLtell、FLflush)から構成されています。これらのロー レベルの IO ルーチンを libc ライブラリ ルーチン(open、fopen、read、fread、write、fwrite...)の代わりに使用することができます。

flib ライブラリの利点は、ファイルのオープン モードによる特定の制限が取り除かれたことです。たとえば、読み取りモードで開かれたパイプにも(例:「pipe:cat file」)書き込むことが可能です。

FLopen 関数では、次の命名規則に従って、操作対象とする論理ファイルのタイプが判定されます(open、popen、fopen、socket などに応じて別々の方式を指定する必要はありません)。現在のところ、認識されるファイル名の形式は次のとおりです。

ファイル名 説明

name

通常のディスク ファイル

name.Z

圧縮されたファイル

mmap:name

メモリ マップされたファイル

pipe:cmd [args]

cmd の標準入力(出力)

fd:#

ファイル記述子番号(# = 0:stdin、1:stdout、2:stderr)

stdin, stdout, stderr

ファイル記述子 0,1,2 の別名

host:name

リモート ホスト上のファイル

user@host:name

リモート ホスト上のファイル(ユーザ アカウントを通じてアクセスされる)

mem:addr

アドレス addr にあるメモリ セグメント

開かれたファイル オブジェクトの特性に応じて、特定の制限が課せられる場合があります(たとえば、パイプに対しては FLseek を実行できません)。

各ファイルは必要に応じてバッファリングされます。メモリ内の移動を最小限に抑えると、それに比例して転送速度が上がります。FLbgnread、FLendread、FLbgnwrite および FLendwrite の各関数を使用すると、ライブラリ内の読み取り/書き込みバッファに直接アクセスできます。メモリ マップされたファイルでこれらの関数を使用すると特に効率的です。

データ フォーマットからの独立性

flib ライブラリに基づくファイル アクセスでは、FLfilter 関数が使用されており、論理ファイルが外部フィルタに渡された上で実際の読み取りや書き込みが行われます。このため、ファイルに保存されたデータのフォーマットをほとんど気にすることなく、ファイルを操作できます。

コントロール

flib ライブラリには、C 言語の標準 IO 関数およびシステム コールの場合と同様のエラー コントロールが組み込まれています。エラーが発生するとステータス変数 flerror の値が変更されますが、その変数値を調べるために複数の関数(FLerror、FLseterror、FLperror、FLstrerror、FLoserror、FLsetoserror)が用意されています。flib ライブラリで扱われるエラー集合は、Linux の標準的なエラー(errno、strerror、h_errno、およびシステムでサポートされている場合は hstrerror)を拡張したものです。

flib ライブラリの IO 関数はエラーが連鎖的に発生しないように設計されていますが、エラーが一度発生した後は、読み取り/書き込み処理を続行しないことを強くお勧めします。

FLconfig 関数を使用すると、flib ライブラリの特定のパラメータ(テンポラリ ファイルの作成、マッピング、自動圧縮/解凍など)を変更できます。

読み取りアクセス時のファイル名の解決に使用されるパスの定義または追加を行うときは、FLsetpath 関数または FLaddpath 関数を呼び出します。

FLswitchpath 関数(頻繁に行われるパス変更を最適化する関数)によってアクティブにされるパスの設定または解除を行うときは、FLbuildpath 関数または FLfreepath 関数を呼び出します。FLsetreorder 関数を使用すると、パスの検索を最適化できます。

構造化ファイル(structured files)

flib には IFF から派生したファイル構造の規則があります。flib のファイル構造ではタグを使用して、「チャンク」と呼ばれるデータのブロックおよび「グループ」と呼ばれるチャンクの構造体を定義します。個々のタグは最大 4 文字からなり、その後にチャンクまたはグループのサイズを表す数値(4 バイトの整数)が続きます。この構造は IFF(Interchange File Format)を少しだけ拡張したものです。すべてのデータは big endian フォーマットで記述されますが、タグは疑似文字列として取り扱われます (バイト交換はコンパイル時に処理されます)。

ブロックのサイズを明示的に指定すると、FLparse 関数など IFF パーサーで認識できないデータはスキップされます。

タグには、ファイル構造(グループ)を定義するタグと、データを含むタグの 2 種類があります。

グループ

ブロックは次の 4 つのタグを使用してグループに編成されます: FORM、CAT、LIST、PROP。サイズの後に続く最初の 4 文字は、グループのタイプを指定するのに使用されます。

FORM タグは、C 言語の struct と似たステートメントによって、グループの始まりを定義します。

FORM 38 TEXT
	CHAR 6 "Times"
	CHAR 12 "Hello World"
EOF

上記のコードは次の C コードと同じ意味です。

struct Text t = {
	char *f = "Times";
	char *c = "Hello World";
};

グループのサイズ(38)は、グループ内のデータのサイズ(6 + 12)に、ヘッダーのサイズ(TEXT 用の 4、CHAR 6 用の 8、CHAR 12 用の 8)を加えた合計値です(この例の場合は、6+12+4+8+8 = 38)。

C 言語のステートメントと同じく、次の例のようにグループをネストできます(ネストとは、入れ子にすることです)。

FORM 52 TEXT
	FORM 8 FONT
		CHAR 6 "Times"
		LONG 4 <12>
		LONG 4 <0>
	CHAR 12 "Hello World"
EOF

上記のコードは次の C コードと同じ意味です。

struct Text t = {
	struct Font f = {
		char *n = "Times";
		int s = 12;
		int d = 0;
	};
	char *string = "Hello World";
};

C 言語のステートメントとまったく同様に、データ型の異なる複数のブロックを同じグループに入れることができます。FORM タグの役割は、別々に取り扱える独立したチャンクの集合(グループ)を分離して、各グループの意味を明確に表すことです。上記の例では、FONT FORM 内の CHAR チャンクと TEXT FORM 内の CHAR チャンクは意味が異なります。すなわち、FORM タグを使用することによって、特定の順序関係を持つチャンクの集合をどのように解釈するかが決まります。

CAT タグは、相互に特定の順序関係を持たない独立したグループを連結します。CAT の主な使用目的は、グループのライブラリ(最初の例の PICT)またはクリップボード(2 番目の例の CLIP)を定義することです。

CAT 3632 PICT
	FORM 1234 PICT ...
	FORM 2378 PICT ...
EOF
CAT 2130 CLIP
	FORM 1234 PICT ...
	FORM 876 DRAW ...
EOF

通常、構造化されたファイル内部での検索は、(メンバーのグループ間に特定の順序関係が存在しない CAT の場合でも)かなり高速になります。これは、ファイルのヘッダーで各グループやチャンクのサイズが指定されているためです。

LIST タグは、特定の順序関係を持つグループ(FORM データ ブロック)の集合を定義します。また、PROP タグと一緒に使用すると、同様の特性を持つグループの集合を簡略に定義できるため、冗長性が排除されます。たとえば、同じサイズの一連のイメージは下記のように表現されます。

個々のイメージの構造は次のとおりです。

FORM .... PICT
	IHDR 32 [image size info]
	BODY ... [image data]
EOF

上記と同じサイズの一連のイメージは、ヘッダー情報が同じなので、次のように定義できます。

LIST ... ANIM
	PROP 44 PICT
		IHDR 32 
	FORM ... PICT
		BODY .... 
	FORM ... PICT
		BODY .... 
	FORM ... PICT
		BODY .... 
EOF

PROP タグで指定された情報は LIST タグの終わり(EOF)まで有効であり、LIST 内部のすべての FORM タグに適用されます。ただし、C 言語のローカル変数の場合と同様に、個々の FORM タグ内部で PROP 情報を再定義することもできます。上記の例では、独自の IHDR ブロックを持たないすべての PICT に対して、PROP タグ内の IHDR ブロックの情報が適用されます。

データ ブロック

データ ブロックは以下で定義されます。

[tag] [size] [data]

例: 単一のイメージの構造は以下のとおりです。

FORM 12304 IMAG
	IHDR 200 ... picture header, size, maps ...
	LINE 800 ... data from line 1 ...
	LINE 800 ... data from line 2 ...
	...

ライブラリの定義

CAT 64200 IMAG
	FORM 12304 IMAG
		IHDR 200
		...
	FORM 12304 IMAG
		...

同じ特性を持つ一連のイメージの定義

LIST 64200 IMAG
	PROP 208 IMAG
		IHDR 200		... Common header ...
	FORM 12394 IMAG
 ...
	FORM 12304 IMAG
		IHDR 200		... Local redefinition ...
		...

メモリ境界に整列する

IFF ブロックは 2 バイトの境界に整列します。ただし、ヘッダーで指定されるサイズではパディングが考慮されていません。一般的に、最近のコンピュータのメモリでは 4 バイトまたは 8 バイトの境界にデータが整列されます。flib ライブラリでは、メモリ境界への整列を指定できるように 8 個の専用タグが用意されています。そのうち、4 個のタグ(FOR4、CAT4、LIS4、PRO4)は 4 バイトの境界への整列を指定するもので、残りの 4 個のタグ(FOR8、CAT8、LIS8、PRO8)は 8 バイトの境界への整列を指定するものです。

データ ブロックは、所属するグループの整列条件を継承します(サブグループを含む。したがって、4 バイトの境界に整列するグループ内に、2 バイトの境界に整列するグループを作成することはできません。その逆は可能です)。

拡張機能(特殊なブロック サイズの指定)

IFF の主要な制限事項の 1 つとして、チャンクまたはグループをファイルに書き込む前に、そのチャンクまたはグループのサイズが分かっていなければならないという点が挙げられます。したがって、ブロックの情報を変更した場合は、ファイル構造の正確なサイズをヘッダーに反映させる必要があります。シーク操作が可能なファイル(ディスク ファイルとメモリ)の場合、この制限事項は特に問題になりませんが、それ以外のファイルについては不都合が発生する場合があります。このため、flib ライブラリでは、ブロックのサイズが不明であることをユーザが事前に指定できる仕組みが用意されています。負の値のブロック サイズが適用されないので、2 つの特別な値がかわりに使われます。FL_szFile は、一度グループが完全に書き込まれた後でサイズを書き込むことを指定する値です。FL_szFifo は、ファイルのシーク操作ができない時にサイズを書き込まないようにする値です。また、構造の終わりを示すのに、特別なゼロ サイズのブロック(GEND)が使われます。

関数

ブロックは、FLgetchunk および FLputchunk の呼び出しを使って読み取りと書き込みを行うことができます。FLbgnget 関数と FLbgnput 関数を呼び出してブロックを開くと、より直接的にブロックを操作できます。FLput 関数と FLget 関数では、FLread および FLwrite と同等の機能をブロック内部で利用できます。FLput または FLget を何回か呼び出した後でブロックを閉じるには、FLendput 関数または FLendget 関数を使用します。

グループを操作するには、FLbgnrgroup、FLbgnWgroup、FLendrgroup、FLendwgroup の各関数を使用します。flib ライブラリには汎用ファイル パーサー FLparse も用意されています。FLparse 関数を使用すると、ファイルのスキャン(解析)や整合性をチェックできます。また、ファイル解析の各ステップ(グループの先頭、グループの終わり)で呼び出されるコールバック関数の指定もできます。

ツール ボックス(Toolbox)

flib ライブラリには、リンク リスト(FLxxxnode と FLxxxlist)、バッファ(FLmalloc と al)、外部フィルタ(FLfilter と FLexec)を操作するためのツールが用意されています。